home *** CD-ROM | disk | FTP | other *** search
/ Freelog 115 / FreelogNo115-MaiJuin2013.iso / Internet / AvantBrowser / asetup.exe / _data / webkit / resources.pak / Unnamed File 000121.unknown < prev    next >
Text File  |  2013-04-03  |  82KB  |  3,266 lines

  1.  
  2.  
  3.  
  4. WebInspector = {};
  5. WebInspector.UIString = function(s) { return s; };
  6.  
  7.  
  8.  
  9.  
  10. WebInspector.HeapSnapshotArraySlice = function(array, start, end)
  11. {
  12. this._array = array;
  13. this._start = start;
  14. this.length = end - start;
  15. }
  16.  
  17. WebInspector.HeapSnapshotArraySlice.prototype = {
  18. item: function(index)
  19. {
  20. return this._array[this._start + index];
  21. },
  22.  
  23. slice: function(start, end)
  24. {
  25. if (typeof end === "undefined")
  26. end = this.length;
  27. return this._array.subarray(this._start + start, this._start + end);
  28. }
  29. }
  30.  
  31.  
  32. WebInspector.HeapSnapshotEdge = function(snapshot, edges, edgeIndex)
  33. {
  34. this._snapshot = snapshot;
  35. this._edges = edges;
  36. this.edgeIndex = edgeIndex || 0;
  37. }
  38.  
  39. WebInspector.HeapSnapshotEdge.prototype = {
  40. clone: function()
  41. {
  42. return new WebInspector.HeapSnapshotEdge(this._snapshot, this._edges, this.edgeIndex);
  43. },
  44.  
  45. hasStringName: function()
  46. {
  47. if (!this.isShortcut())
  48. return this._hasStringName();
  49. return isNaN(parseInt(this._name(), 10));
  50. },
  51.  
  52. isElement: function()
  53. {
  54. return this._type() === this._snapshot._edgeElementType;
  55. },
  56.  
  57. isHidden: function()
  58. {
  59. return this._type() === this._snapshot._edgeHiddenType;
  60. },
  61.  
  62. isWeak: function()
  63. {
  64. return this._type() === this._snapshot._edgeWeakType;
  65. },
  66.  
  67. isInternal: function()
  68. {
  69. return this._type() === this._snapshot._edgeInternalType;
  70. },
  71.  
  72. isInvisible: function()
  73. {
  74. return this._type() === this._snapshot._edgeInvisibleType;
  75. },
  76.  
  77. isShortcut: function()
  78. {
  79. return this._type() === this._snapshot._edgeShortcutType;
  80. },
  81.  
  82. name: function()
  83. {
  84. if (!this.isShortcut())
  85. return this._name();
  86. var numName = parseInt(this._name(), 10);
  87. return isNaN(numName) ? this._name() : numName;
  88. },
  89.  
  90. node: function()
  91. {
  92. return new WebInspector.HeapSnapshotNode(this._snapshot, this.nodeIndex());
  93. },
  94.  
  95. nodeIndex: function()
  96. {
  97. return this._edges.item(this.edgeIndex + this._snapshot._edgeToNodeOffset);
  98. },
  99.  
  100. rawEdges: function()
  101. {
  102. return this._edges;
  103. },
  104.  
  105. toString: function()
  106. {
  107. var name = this.name();
  108. switch (this.type()) {
  109. case "context": return "->" + name;
  110. case "element": return "[" + name + "]";
  111. case "weak": return "[[" + name + "]]";
  112. case "property":
  113. return name.indexOf(" ") === -1 ? "." + name : "[\"" + name + "\"]";
  114. case "shortcut":
  115. if (typeof name === "string")
  116. return name.indexOf(" ") === -1 ? "." + name : "[\"" + name + "\"]";
  117. else
  118. return "[" + name + "]";
  119. case "internal":
  120. case "hidden":
  121. case "invisible":
  122. return "{" + name + "}";
  123. };
  124. return "?" + name + "?";
  125. },
  126.  
  127. type: function()
  128. {
  129. return this._snapshot._edgeTypes[this._type()];
  130. },
  131.  
  132. _hasStringName: function()
  133. {
  134. return !this.isElement() && !this.isHidden() && !this.isWeak();
  135. },
  136.  
  137. _name: function()
  138. {
  139. return this._hasStringName() ? this._snapshot._strings[this._nameOrIndex()] : this._nameOrIndex();
  140. },
  141.  
  142. _nameOrIndex: function()
  143. {
  144. return this._edges.item(this.edgeIndex + this._snapshot._edgeNameOffset);
  145. },
  146.  
  147. _type: function()
  148. {
  149. return this._edges.item(this.edgeIndex + this._snapshot._edgeTypeOffset);
  150. }
  151. };
  152.  
  153.  
  154. WebInspector.HeapSnapshotEdgeIterator = function(edge)
  155. {
  156. this.edge = edge;
  157. }
  158.  
  159. WebInspector.HeapSnapshotEdgeIterator.prototype = {
  160. first: function()
  161. {
  162. this.edge.edgeIndex = 0;
  163. },
  164.  
  165. hasNext: function()
  166. {
  167. return this.edge.edgeIndex < this.edge._edges.length;
  168. },
  169.  
  170. index: function()
  171. {
  172. return this.edge.edgeIndex;
  173. },
  174.  
  175. setIndex: function(newIndex)
  176. {
  177. this.edge.edgeIndex = newIndex;
  178. },
  179.  
  180. item: function()
  181. {
  182. return this.edge;
  183. },
  184.  
  185. next: function()
  186. {
  187. this.edge.edgeIndex += this.edge._snapshot._edgeFieldsCount;
  188. }
  189. };
  190.  
  191.  
  192. WebInspector.HeapSnapshotRetainerEdge = function(snapshot, retainedNodeIndex, retainerIndex)
  193. {
  194. this._snapshot = snapshot;
  195. this._retainedNodeIndex = retainedNodeIndex;
  196.  
  197. var retainedNodeOrdinal = retainedNodeIndex / snapshot._nodeFieldCount;
  198. this._firstRetainer = snapshot._firstRetainerIndex[retainedNodeOrdinal];
  199. this._retainersCount = snapshot._firstRetainerIndex[retainedNodeOrdinal + 1] - this._firstRetainer;
  200.  
  201. this.setRetainerIndex(retainerIndex);
  202. }
  203.  
  204. WebInspector.HeapSnapshotRetainerEdge.prototype = {
  205. clone: function()
  206. {
  207. return new WebInspector.HeapSnapshotRetainerEdge(this._snapshot, this._retainedNodeIndex, this.retainerIndex());
  208. },
  209.  
  210. hasStringName: function()
  211. {
  212. return this._edge().hasStringName();
  213. },
  214.  
  215. isElement: function()
  216. {
  217. return this._edge().isElement();
  218. },
  219.  
  220. isHidden: function()
  221. {
  222. return this._edge().isHidden();
  223. },
  224.  
  225. isInternal: function()
  226. {
  227. return this._edge().isInternal();
  228. },
  229.  
  230. isInvisible: function()
  231. {
  232. return this._edge().isInvisible();
  233. },
  234.  
  235. isShortcut: function()
  236. {
  237. return this._edge().isShortcut();
  238. },
  239.  
  240. isWeak: function()
  241. {
  242. return this._edge().isWeak();
  243. },
  244.  
  245. name: function()
  246. {
  247. return this._edge().name();
  248. },
  249.  
  250. node: function()
  251. {
  252. return this._node();
  253. },
  254.  
  255. nodeIndex: function()
  256. {
  257. return this._nodeIndex;
  258. },
  259.  
  260. retainerIndex: function()
  261. {
  262. return this._retainerIndex;
  263. },
  264.  
  265. setRetainerIndex: function(newIndex)
  266. {
  267. if (newIndex !== this._retainerIndex) {
  268. this._retainerIndex = newIndex;
  269. this.edgeIndex = newIndex;
  270. }
  271. },
  272.  
  273. set edgeIndex(edgeIndex)
  274. {
  275. var retainerIndex = this._firstRetainer + edgeIndex;
  276. this._globalEdgeIndex = this._snapshot._retainingEdges[retainerIndex];
  277. this._nodeIndex = this._snapshot._retainingNodes[retainerIndex];
  278. delete this._edgeInstance;
  279. delete this._nodeInstance;
  280. },
  281.  
  282. _node: function()
  283. {
  284. if (!this._nodeInstance)
  285. this._nodeInstance = new WebInspector.HeapSnapshotNode(this._snapshot, this._nodeIndex);
  286. return this._nodeInstance;
  287. },
  288.  
  289. _edge: function()
  290. {
  291. if (!this._edgeInstance) {
  292. var edgeIndex = this._globalEdgeIndex - this._node()._edgeIndexesStart();
  293. this._edgeInstance = new WebInspector.HeapSnapshotEdge(this._snapshot, this._node().rawEdges(), edgeIndex);
  294. }
  295. return this._edgeInstance;
  296. },
  297.  
  298. toString: function()
  299. {
  300. return this._edge().toString();
  301. },
  302.  
  303. type: function()
  304. {
  305. return this._edge().type();
  306. }
  307. }
  308.  
  309.  
  310. WebInspector.HeapSnapshotRetainerEdgeIterator = function(retainer)
  311. {
  312. this.retainer = retainer;
  313. }
  314.  
  315. WebInspector.HeapSnapshotRetainerEdgeIterator.prototype = {
  316. first: function()
  317. {
  318. this.retainer.setRetainerIndex(0);
  319. },
  320.  
  321. hasNext: function()
  322. {
  323. return this.retainer.retainerIndex() < this.retainer._retainersCount;
  324. },
  325.  
  326. index: function()
  327. {
  328. return this.retainer.retainerIndex();
  329. },
  330.  
  331. setIndex: function(newIndex)
  332. {
  333. this.retainer.setRetainerIndex(newIndex);
  334. },
  335.  
  336. item: function()
  337. {
  338. return this.retainer;
  339. },
  340.  
  341. next: function()
  342. {
  343. this.retainer.setRetainerIndex(this.retainer.retainerIndex() + 1);
  344. }
  345. };
  346.  
  347.  
  348. WebInspector.HeapSnapshotNode = function(snapshot, nodeIndex)
  349. {
  350. this._snapshot = snapshot;
  351. this._firstNodeIndex = nodeIndex;
  352. this.nodeIndex = nodeIndex;
  353. }
  354.  
  355. WebInspector.HeapSnapshotNode.prototype = {
  356. canBeQueried: function()
  357. {
  358. var flags = this._snapshot._flagsOfNode(this);
  359. return !!(flags & this._snapshot._nodeFlags.canBeQueried);
  360. },
  361.  
  362. isPageObject: function()
  363. {
  364. var flags = this._snapshot._flagsOfNode(this);
  365. return !!(flags & this._snapshot._nodeFlags.pageObject);
  366. },
  367.  
  368. distanceToWindow: function()
  369. {
  370. return this._snapshot._distancesToWindow[this.nodeIndex / this._snapshot._nodeFieldCount];
  371. },
  372.  
  373. className: function()
  374. {
  375. var type = this.type();
  376. switch (type) {
  377. case "hidden":
  378. return WebInspector.UIString("(system)");
  379. case "object":
  380. case "native":
  381. return this.name();
  382. case "code":
  383. return WebInspector.UIString("(compiled code)");
  384. default:
  385. return "(" + type + ")";
  386. }
  387. },
  388.  
  389. classIndex: function()
  390. {
  391. var snapshot = this._snapshot;
  392. var nodes = snapshot._nodes;
  393. var type = nodes[this.nodeIndex + snapshot._nodeTypeOffset];;
  394. if (type === snapshot._nodeObjectType || type === snapshot._nodeNativeType)
  395. return nodes[this.nodeIndex + snapshot._nodeNameOffset];
  396. return -1 - type;
  397. },
  398.  
  399. dominatorIndex: function()
  400. {
  401. var nodeFieldCount = this._snapshot._nodeFieldCount;
  402. return this._snapshot._dominatorsTree[this.nodeIndex / this._snapshot._nodeFieldCount] * nodeFieldCount;
  403. },
  404.  
  405. edges: function()
  406. {
  407. return new WebInspector.HeapSnapshotEdgeIterator(new WebInspector.HeapSnapshotEdge(this._snapshot, this.rawEdges()));
  408. },
  409.  
  410. edgesCount: function()
  411. {
  412. return (this._edgeIndexesEnd() - this._edgeIndexesStart()) / this._snapshot._edgeFieldsCount;
  413. },
  414.  
  415. flags: function()
  416. {
  417. return this._snapshot._flagsOfNode(this);
  418. },
  419.  
  420. id: function()
  421. {
  422. var snapshot = this._snapshot;
  423. return snapshot._nodes[this.nodeIndex + snapshot._nodeIdOffset];
  424. },
  425.  
  426. isHidden: function()
  427. {
  428. return this._type() === this._snapshot._nodeHiddenType;
  429. },
  430.  
  431. isNative: function()
  432. {
  433. return this._type() === this._snapshot._nodeNativeType;
  434. },
  435.  
  436. isSynthetic: function()
  437. {
  438. return this._type() === this._snapshot._nodeSyntheticType;
  439. },
  440.  
  441. isWindow: function()
  442. {
  443. const windowRE = /^Window/;
  444. return windowRE.test(this.name());
  445. },
  446.  
  447. isDetachedDOMTreesRoot: function()
  448. {
  449. return this.name() === "(Detached DOM trees)";
  450. },
  451.  
  452. isDetachedDOMTree: function()
  453. {
  454. const detachedDOMTreeRE = /^Detached DOM tree/;
  455. return detachedDOMTreeRE.test(this.className());
  456. },
  457.  
  458. isRoot: function()
  459. {
  460. return this.nodeIndex === this._snapshot._rootNodeIndex;
  461. },
  462.  
  463. name: function()
  464. {
  465. return this._snapshot._strings[this._name()];
  466. },
  467.  
  468. rawEdges: function()
  469. {
  470. return new WebInspector.HeapSnapshotArraySlice(this._snapshot._containmentEdges, this._edgeIndexesStart(), this._edgeIndexesEnd());
  471. },
  472.  
  473. retainedSize: function()
  474. {
  475. var snapshot = this._snapshot;
  476. return snapshot._nodes[this.nodeIndex + snapshot._nodeRetainedSizeOffset];
  477. },
  478.  
  479. retainers: function()
  480. {
  481. return new WebInspector.HeapSnapshotRetainerEdgeIterator(new WebInspector.HeapSnapshotRetainerEdge(this._snapshot, this.nodeIndex, 0));
  482. },
  483.  
  484. selfSize: function()
  485. {
  486. var snapshot = this._snapshot;
  487. return snapshot._nodes[this.nodeIndex + snapshot._nodeSelfSizeOffset];
  488. },
  489.  
  490. type: function()
  491. {
  492. return this._snapshot._nodeTypes[this._type()];
  493. },
  494.  
  495. _name: function()
  496. {
  497. var snapshot = this._snapshot;
  498. return snapshot._nodes[this.nodeIndex + snapshot._nodeNameOffset];
  499. },
  500.  
  501. _edgeIndexesStart: function()
  502. {
  503. return this._snapshot._firstEdgeIndexes[this._ordinal()];
  504. },
  505.  
  506. _edgeIndexesEnd: function()
  507. {
  508. return this._snapshot._firstEdgeIndexes[this._ordinal() + 1];
  509. },
  510.  
  511. _ordinal: function()
  512. {
  513. return this.nodeIndex / this._snapshot._nodeFieldCount;
  514. },
  515.  
  516. _nextNodeIndex: function()
  517. {
  518. return this.nodeIndex + this._snapshot._nodeFieldCount;
  519. },
  520.  
  521. _type: function()
  522. {
  523. var snapshot = this._snapshot;
  524. return snapshot._nodes[this.nodeIndex + snapshot._nodeTypeOffset];
  525. }
  526. };
  527.  
  528.  
  529. WebInspector.HeapSnapshotNodeIterator = function(node)
  530. {
  531. this.node = node;
  532. this._nodesLength = node._snapshot._nodes.length;
  533. }
  534.  
  535. WebInspector.HeapSnapshotNodeIterator.prototype = {
  536. first: function()
  537. {
  538. this.node.nodeIndex = this.node._firstNodeIndex;
  539. },
  540.  
  541. hasNext: function()
  542. {
  543. return this.node.nodeIndex < this._nodesLength;
  544. },
  545.  
  546. index: function()
  547. {
  548. return this.node.nodeIndex;
  549. },
  550.  
  551. setIndex: function(newIndex)
  552. {
  553. this.node.nodeIndex = newIndex;
  554. },
  555.  
  556. item: function()
  557. {
  558. return this.node;
  559. },
  560.  
  561. next: function()
  562. {
  563. this.node.nodeIndex = this.node._nextNodeIndex();
  564. }
  565. }
  566.  
  567.  
  568. WebInspector.HeapSnapshot = function(profile)
  569. {
  570. this.uid = profile.snapshot.uid;
  571. this._nodes = profile.nodes;
  572. this._containmentEdges = profile.edges;
  573.  
  574. this._metaNode = profile.snapshot.meta;
  575. this._strings = profile.strings;
  576.  
  577. this._snapshotDiffs = {};
  578. this._aggregatesForDiff = null;
  579.  
  580. this._init();
  581. }
  582.  
  583.  
  584. function HeapSnapshotMetainfo()
  585. {
  586.  
  587. this.node_fields = [];
  588. this.node_types = [];
  589. this.edge_fields = [];
  590. this.edge_types = [];
  591.  
  592.  
  593. this.fields = [];
  594. this.types = [];
  595. }
  596.  
  597.  
  598. function HeapSnapshotHeader()
  599. {
  600.  
  601. this.title = "";
  602. this.uid = 0;
  603. this.meta = new HeapSnapshotMetainfo();
  604. this.node_count = 0;
  605. this.edge_count = 0;
  606. }
  607.  
  608. WebInspector.HeapSnapshot.prototype = {
  609. _init: function()
  610. {
  611. var meta = this._metaNode;
  612. this._rootNodeIndex = 0;
  613.  
  614. this._nodeTypeOffset = meta.node_fields.indexOf("type");
  615. this._nodeNameOffset = meta.node_fields.indexOf("name");
  616. this._nodeIdOffset = meta.node_fields.indexOf("id");
  617. this._nodeSelfSizeOffset = meta.node_fields.indexOf("self_size");
  618. this._nodeEdgeCountOffset = meta.node_fields.indexOf("edge_count");
  619. this._nodeFieldCount = meta.node_fields.length;
  620.  
  621. this._nodeTypes = meta.node_types[this._nodeTypeOffset];
  622. this._nodeHiddenType = this._nodeTypes.indexOf("hidden");
  623. this._nodeObjectType = this._nodeTypes.indexOf("object");
  624. this._nodeNativeType = this._nodeTypes.indexOf("native");
  625. this._nodeCodeType = this._nodeTypes.indexOf("code");
  626. this._nodeSyntheticType = this._nodeTypes.indexOf("synthetic");
  627.  
  628. this._edgeFieldsCount = meta.edge_fields.length;
  629. this._edgeTypeOffset = meta.edge_fields.indexOf("type");
  630. this._edgeNameOffset = meta.edge_fields.indexOf("name_or_index");
  631. this._edgeToNodeOffset = meta.edge_fields.indexOf("to_node");
  632.  
  633. this._edgeTypes = meta.edge_types[this._edgeTypeOffset];
  634. this._edgeTypes.push("invisible");
  635. this._edgeElementType = this._edgeTypes.indexOf("element");
  636. this._edgeHiddenType = this._edgeTypes.indexOf("hidden");
  637. this._edgeInternalType = this._edgeTypes.indexOf("internal");
  638. this._edgeShortcutType = this._edgeTypes.indexOf("shortcut");
  639. this._edgeWeakType = this._edgeTypes.indexOf("weak");
  640. this._edgeInvisibleType = this._edgeTypes.indexOf("invisible");
  641.  
  642. this._nodeFlags = { 
  643. canBeQueried: 1,
  644. detachedDOMTreeNode: 2,
  645. pageObject: 4, 
  646.  
  647. visitedMarkerMask: 0x0ffff, 
  648. visitedMarker:     0x10000  
  649. };
  650.  
  651. this.nodeCount = this._nodes.length / this._nodeFieldCount;
  652. this._edgeCount = this._containmentEdges.length / this._edgeFieldsCount;
  653.  
  654. this._buildEdgeIndexes();
  655. this._markInvisibleEdges();
  656. this._buildRetainers();
  657. this._calculateFlags();
  658. this._calculateObjectToWindowDistance();
  659. var result = this._buildPostOrderIndex();
  660.  
  661. this._dominatorsTree = this._buildDominatorTree(result.postOrderIndex2NodeOrdinal, result.nodeOrdinal2PostOrderIndex);
  662. this._calculateRetainedSizes(result.postOrderIndex2NodeOrdinal);
  663. this._buildDominatedNodes();
  664. },
  665.  
  666. _buildEdgeIndexes: function()
  667. {
  668.  
  669. if (this._nodeEdgeCountOffset === -1) {
  670. var nodes = this._nodes;
  671. var nodeCount = this.nodeCount;
  672. var firstEdgeIndexes = this._firstEdgeIndexes = new Uint32Array(nodeCount + 1);
  673. var nodeFieldCount = this._nodeFieldCount;
  674. var nodeEdgesIndexOffset = this._metaNode.node_fields.indexOf("edges_index");
  675. firstEdgeIndexes[nodeCount] = this._containmentEdges.length;
  676. for (var nodeOrdinal = 0; nodeOrdinal < nodeCount; ++nodeOrdinal) {
  677. firstEdgeIndexes[nodeOrdinal] = nodes[nodeOrdinal * nodeFieldCount + nodeEdgesIndexOffset];
  678. }
  679. return;
  680. }
  681.  
  682. var nodes = this._nodes;
  683. var nodeCount = this.nodeCount;
  684. var firstEdgeIndexes = this._firstEdgeIndexes = new Uint32Array(nodeCount + 1);
  685. var nodeFieldCount = this._nodeFieldCount;
  686. var edgeFieldsCount = this._edgeFieldsCount;
  687. var nodeEdgeCountOffset = this._nodeEdgeCountOffset;
  688. firstEdgeIndexes[nodeCount] = this._containmentEdges.length;
  689. for (var nodeOrdinal = 0, edgeIndex = 0; nodeOrdinal < nodeCount; ++nodeOrdinal) {
  690. firstEdgeIndexes[nodeOrdinal] = edgeIndex;
  691. edgeIndex += nodes[nodeOrdinal * nodeFieldCount + nodeEdgeCountOffset] * edgeFieldsCount;
  692. }
  693. },
  694.  
  695. _buildRetainers: function()
  696. {
  697. var retainingNodes = this._retainingNodes = new Uint32Array(this._edgeCount);
  698. var retainingEdges = this._retainingEdges = new Uint32Array(this._edgeCount);
  699.  
  700.  
  701. var firstRetainerIndex = this._firstRetainerIndex = new Uint32Array(this.nodeCount + 1);
  702.  
  703. var containmentEdges = this._containmentEdges;
  704. var edgeFieldsCount = this._edgeFieldsCount;
  705. var nodeFieldCount = this._nodeFieldCount;
  706. var edgeToNodeOffset = this._edgeToNodeOffset;
  707. var nodes = this._nodes;
  708. var firstEdgeIndexes = this._firstEdgeIndexes;
  709. var nodeCount = this.nodeCount;
  710.  
  711. for (var toNodeFieldIndex = edgeToNodeOffset, l = containmentEdges.length; toNodeFieldIndex < l; toNodeFieldIndex += edgeFieldsCount) {
  712. var toNodeIndex = containmentEdges[toNodeFieldIndex];
  713. if (toNodeIndex % nodeFieldCount)
  714. throw new Error("Invalid toNodeIndex " + toNodeIndex);
  715. ++firstRetainerIndex[toNodeIndex / nodeFieldCount];
  716. }
  717. for (var i = 0, firstUnusedRetainerSlot = 0; i < nodeCount; i++) {
  718. var retainersCount = firstRetainerIndex[i];
  719. firstRetainerIndex[i] = firstUnusedRetainerSlot;
  720. retainingNodes[firstUnusedRetainerSlot] = retainersCount;
  721. firstUnusedRetainerSlot += retainersCount;
  722. }
  723. firstRetainerIndex[nodeCount] = retainingNodes.length;
  724.  
  725. var nextNodeFirstEdgeIndex = firstEdgeIndexes[0];
  726. for (var srcNodeOrdinal = 0; srcNodeOrdinal < nodeCount; ++srcNodeOrdinal) {
  727. var firstEdgeIndex = nextNodeFirstEdgeIndex;
  728. nextNodeFirstEdgeIndex = firstEdgeIndexes[srcNodeOrdinal + 1];
  729. var srcNodeIndex = srcNodeOrdinal * nodeFieldCount;
  730. for (var edgeIndex = firstEdgeIndex; edgeIndex < nextNodeFirstEdgeIndex; edgeIndex += edgeFieldsCount) {
  731. var toNodeIndex = containmentEdges[edgeIndex + edgeToNodeOffset];
  732. if (toNodeIndex % nodeFieldCount)
  733. throw new Error("Invalid toNodeIndex " + toNodeIndex);
  734. var firstRetainerSlotIndex = firstRetainerIndex[toNodeIndex / nodeFieldCount];
  735. var nextUnusedRetainerSlotIndex = firstRetainerSlotIndex + (--retainingNodes[firstRetainerSlotIndex]);
  736. retainingNodes[nextUnusedRetainerSlotIndex] = srcNodeIndex;
  737. retainingEdges[nextUnusedRetainerSlotIndex] = edgeIndex;
  738. }
  739. }
  740. },
  741.  
  742. dispose: function()
  743. {
  744. delete this._nodes;
  745. delete this._strings;
  746. delete this._retainingEdges;
  747. delete this._retainingNodes;
  748. delete this._firstRetainerIndex;
  749. if (this._aggregates) {
  750. delete this._aggregates;
  751. delete this._aggregatesSortedFlags;
  752. }
  753. delete this._dominatedNodes;
  754. delete this._firstDominatedNodeIndex;
  755. delete this._flags;
  756. delete this._distancesToWindow;
  757. delete this._dominatorsTree;
  758. },
  759.  
  760. _allNodes: function()
  761. {
  762. return new WebInspector.HeapSnapshotNodeIterator(this.rootNode());
  763. },
  764.  
  765. rootNode: function()
  766. {
  767. return new WebInspector.HeapSnapshotNode(this, this._rootNodeIndex);
  768. },
  769.  
  770. get rootNodeIndex()
  771. {
  772. return this._rootNodeIndex;
  773. },
  774.  
  775. get totalSize()
  776. {
  777. return this.rootNode().retainedSize();
  778. },
  779.  
  780. _getDominatedIndex: function(nodeIndex)
  781. {
  782. if (nodeIndex % this._nodeFieldCount)
  783. throw new Error("Invalid nodeIndex: " + nodeIndex);
  784. return this._firstDominatedNodeIndex[nodeIndex / this._nodeFieldCount];
  785. },
  786.  
  787. _dominatedNodesOfNode: function(node)
  788. {
  789. var dominatedIndexFrom = this._getDominatedIndex(node.nodeIndex);
  790. var dominatedIndexTo = this._getDominatedIndex(node._nextNodeIndex());
  791. return new WebInspector.HeapSnapshotArraySlice(this._dominatedNodes, dominatedIndexFrom, dominatedIndexTo);
  792. },
  793.  
  794. _flagsOfNode: function(node)
  795. {
  796. return this._flags[node.nodeIndex / this._nodeFieldCount];
  797. },
  798.  
  799.  
  800. aggregates: function(sortedIndexes, key, filterString)
  801. {
  802. if (!this._aggregates) {
  803. this._aggregates = {};
  804. this._aggregatesSortedFlags = {};
  805. }
  806.  
  807. var aggregatesByClassName = this._aggregates[key];
  808. if (aggregatesByClassName) {
  809. if (sortedIndexes && !this._aggregatesSortedFlags[key]) {
  810. this._sortAggregateIndexes(aggregatesByClassName);
  811. this._aggregatesSortedFlags[key] = sortedIndexes;
  812. }
  813. return aggregatesByClassName;
  814. }
  815.  
  816. var filter;
  817. if (filterString)
  818. filter = this._parseFilter(filterString);
  819.  
  820. var aggregates = this._buildAggregates(filter);
  821. this._calculateClassesRetainedSize(aggregates.aggregatesByClassIndex, filter);
  822. aggregatesByClassName = aggregates.aggregatesByClassName;
  823.  
  824. if (sortedIndexes)
  825. this._sortAggregateIndexes(aggregatesByClassName);
  826.  
  827. this._aggregatesSortedFlags[key] = sortedIndexes;
  828. this._aggregates[key] = aggregatesByClassName;
  829.  
  830. return aggregatesByClassName;
  831. },
  832.  
  833. aggregatesForDiff: function()
  834. {
  835. if (this._aggregatesForDiff)
  836. return this._aggregatesForDiff;
  837.  
  838. var aggregatesByClassName = this.aggregates(true, "allObjects");
  839. this._aggregatesForDiff  = {};
  840.  
  841. var node = new WebInspector.HeapSnapshotNode(this);
  842. for (var className in aggregatesByClassName) {
  843. var aggregate = aggregatesByClassName[className];
  844. var indexes = aggregate.idxs;
  845. var ids = new Array(indexes.length);
  846. var selfSizes = new Array(indexes.length);
  847. for (var i = 0; i < indexes.length; i++) {
  848. node.nodeIndex = indexes[i];
  849. ids[i] = node.id();
  850. selfSizes[i] = node.selfSize();
  851. }
  852.  
  853. this._aggregatesForDiff[className] = {
  854. indexes: indexes,
  855. ids: ids,
  856. selfSizes: selfSizes
  857. };
  858. }
  859. return this._aggregatesForDiff;
  860. },
  861.  
  862. _calculateObjectToWindowDistance: function()
  863. {
  864. var nodeFieldCount = this._nodeFieldCount;
  865. var distances = new Uint32Array(this.nodeCount);
  866.  
  867.  
  868. var nodesToVisit = new Uint32Array(this.nodeCount);
  869. var nodesToVisitLength = 0;
  870. for (var iter = this.rootNode().edges(); iter.hasNext(); iter.next()) {
  871. var node = iter.edge.node();
  872. if (node.isWindow()) {
  873. nodesToVisit[nodesToVisitLength++] = node.nodeIndex;
  874. distances[node.nodeIndex / nodeFieldCount] = 1;
  875. }
  876. }
  877. this._bfs(nodesToVisit, nodesToVisitLength, distances);
  878.  
  879.  
  880. nodesToVisitLength = 0;
  881. nodesToVisit[nodesToVisitLength++] = this._rootNodeIndex;
  882. distances[this._rootNodeIndex / nodeFieldCount] = 1;
  883. this._bfs(nodesToVisit, nodesToVisitLength, distances);
  884. this._distancesToWindow = distances;
  885. },
  886.  
  887. _bfs: function(nodesToVisit, nodesToVisitLength, distances)
  888. {
  889.  
  890. var edgeFieldsCount = this._edgeFieldsCount;
  891. var nodeFieldCount = this._nodeFieldCount;
  892. var containmentEdges = this._containmentEdges;
  893. var firstEdgeIndexes = this._firstEdgeIndexes;
  894. var edgeToNodeOffset = this._edgeToNodeOffset;
  895. var edgeTypeOffset = this._edgeTypeOffset;
  896. var nodes = this._nodes;
  897. var nodeCount = this.nodeCount;
  898. var containmentEdgesLength = containmentEdges.length;
  899. var edgeWeakType = this._edgeWeakType;
  900. var edgeShortcutType = this._edgeShortcutType;
  901.  
  902. var index = 0;
  903. while (index < nodesToVisitLength) {
  904. var nodeIndex = nodesToVisit[index++]; 
  905. var nodeOrdinal = nodeIndex / nodeFieldCount;
  906. var distance = distances[nodeOrdinal] + 1;
  907. var firstEdgeIndex = firstEdgeIndexes[nodeOrdinal];
  908. var edgesEnd = firstEdgeIndexes[nodeOrdinal + 1];
  909. for (var edgeIndex = firstEdgeIndex; edgeIndex < edgesEnd; edgeIndex += edgeFieldsCount) {
  910. var edgeType = containmentEdges[edgeIndex + edgeTypeOffset];
  911. if (edgeType == edgeWeakType)
  912. continue;
  913. var childNodeIndex = containmentEdges[edgeIndex + edgeToNodeOffset];
  914. var childNodeOrdinal = childNodeIndex / nodeFieldCount;
  915. if (distances[childNodeOrdinal])
  916. continue;
  917. distances[childNodeOrdinal] = distance;
  918. nodesToVisit[nodesToVisitLength++] = childNodeIndex;
  919. }
  920. }
  921. if (nodesToVisitLength > nodeCount)
  922. throw new Error("BFS failed. Nodes to visit (" + nodesToVisitLength + ") is more than nodes count (" + nodeCount + ")");
  923. },
  924.  
  925. _buildAggregates: function(filter)
  926. {
  927. var aggregates = {};
  928. var aggregatesByClassName = {};
  929. var classIndexes = [];
  930. var nodes = this._nodes;
  931. var flags = this._flags;
  932. var nodesLength = nodes.length;
  933. var nodeNativeType = this._nodeNativeType;
  934. var nodeFieldCount = this._nodeFieldCount;
  935. var selfSizeOffset = this._nodeSelfSizeOffset;
  936. var nodeTypeOffset = this._nodeTypeOffset;
  937. var pageObjectFlag = this._nodeFlags.pageObject;
  938. var node = new WebInspector.HeapSnapshotNode(this, this._rootNodeIndex);
  939. var distancesToWindow = this._distancesToWindow;
  940.  
  941. for (var nodeIndex = this._rootNodeIndex; nodeIndex < nodesLength; nodeIndex += nodeFieldCount) {
  942. var nodeOrdinal = nodeIndex / nodeFieldCount;
  943. if (!(flags[nodeOrdinal] & pageObjectFlag))
  944. continue;
  945. node.nodeIndex = nodeIndex;
  946. if (filter && !filter(node))
  947. continue;
  948. var selfSize = nodes[nodeIndex + selfSizeOffset];
  949. if (!selfSize && nodes[nodeIndex + nodeTypeOffset] !== nodeNativeType)
  950. continue;
  951. var classIndex = node.classIndex();
  952. if (!(classIndex in aggregates)) {
  953. var nodeType = node.type();
  954. var nameMatters = nodeType === "object" || nodeType === "native";
  955. var value = {
  956. count: 1,
  957. distanceToWindow: distancesToWindow[nodeOrdinal],
  958. self: selfSize,
  959. maxRet: 0,
  960. type: nodeType,
  961. name: nameMatters ? node.name() : null,
  962. idxs: [nodeIndex]
  963. };
  964. aggregates[classIndex] = value;
  965. classIndexes.push(classIndex);
  966. aggregatesByClassName[node.className()] = value;
  967. } else {
  968. var clss = aggregates[classIndex];
  969. clss.distanceToWindow = Math.min(clss.distanceToWindow, distancesToWindow[nodeOrdinal]);
  970. ++clss.count;
  971. clss.self += selfSize;
  972. clss.idxs.push(nodeIndex);
  973. }
  974. }
  975.  
  976.  
  977. for (var i = 0, l = classIndexes.length; i < l; ++i) {
  978. var classIndex = classIndexes[i];
  979. aggregates[classIndex].idxs = aggregates[classIndex].idxs.slice();
  980. }
  981. return {aggregatesByClassName: aggregatesByClassName, aggregatesByClassIndex: aggregates};
  982. },
  983.  
  984. _calculateClassesRetainedSize: function(aggregates, filter)
  985. {
  986. var rootNodeIndex = this._rootNodeIndex;
  987. var node = new WebInspector.HeapSnapshotNode(this, rootNodeIndex);
  988. var list = [rootNodeIndex];
  989. var sizes = [-1];
  990. var classes = [];
  991. var seenClassNameIndexes = {};
  992. var nodeFieldCount = this._nodeFieldCount;
  993. var nodeTypeOffset = this._nodeTypeOffset;
  994. var nodeNativeType = this._nodeNativeType;
  995. var dominatedNodes = this._dominatedNodes;
  996. var nodes = this._nodes;
  997. var flags = this._flags;
  998. var pageObjectFlag = this._nodeFlags.pageObject;
  999. var firstDominatedNodeIndex = this._firstDominatedNodeIndex;
  1000.  
  1001. while (list.length) {
  1002. var nodeIndex = list.pop();
  1003. node.nodeIndex = nodeIndex;
  1004. var classIndex = node.classIndex();
  1005. var seen = !!seenClassNameIndexes[classIndex];
  1006. var nodeOrdinal = nodeIndex / nodeFieldCount;
  1007. var dominatedIndexFrom = firstDominatedNodeIndex[nodeOrdinal];
  1008. var dominatedIndexTo = firstDominatedNodeIndex[nodeOrdinal + 1];
  1009.  
  1010. if (!seen &&
  1011. (flags[nodeOrdinal] & pageObjectFlag) &&
  1012. (!filter || filter(node)) &&
  1013. (node.selfSize() || nodes[nodeIndex + nodeTypeOffset] === nodeNativeType)
  1014. ) {
  1015. aggregates[classIndex].maxRet += node.retainedSize();
  1016. if (dominatedIndexFrom !== dominatedIndexTo) {
  1017. seenClassNameIndexes[classIndex] = true;
  1018. sizes.push(list.length);
  1019. classes.push(classIndex);
  1020. }
  1021. }
  1022. for (var i = dominatedIndexFrom; i < dominatedIndexTo; i++)
  1023. list.push(dominatedNodes[i]);
  1024.  
  1025. var l = list.length;
  1026. while (sizes[sizes.length - 1] === l) {
  1027. sizes.pop();
  1028. classIndex = classes.pop();
  1029. seenClassNameIndexes[classIndex] = false;
  1030. }
  1031. }
  1032. },
  1033.  
  1034. _sortAggregateIndexes: function(aggregates)
  1035. {
  1036. var nodeA = new WebInspector.HeapSnapshotNode(this);
  1037. var nodeB = new WebInspector.HeapSnapshotNode(this);
  1038. for (var clss in aggregates)
  1039. aggregates[clss].idxs.sort(
  1040. function(idxA, idxB) {
  1041. nodeA.nodeIndex = idxA;
  1042. nodeB.nodeIndex = idxB;
  1043. return nodeA.id() < nodeB.id() ? -1 : 1;
  1044. });
  1045. },
  1046.  
  1047. _buildPostOrderIndex: function()
  1048. {
  1049. var nodeFieldCount = this._nodeFieldCount;
  1050. var nodes = this._nodes;
  1051. var nodeCount = this.nodeCount;
  1052. var rootNodeOrdinal = this._rootNodeIndex / nodeFieldCount;
  1053.  
  1054. var edgeFieldsCount = this._edgeFieldsCount;
  1055. var edgeTypeOffset = this._edgeTypeOffset;
  1056. var edgeToNodeOffset = this._edgeToNodeOffset;
  1057. var edgeShortcutType = this._edgeShortcutType;
  1058. var firstEdgeIndexes = this._firstEdgeIndexes;
  1059. var containmentEdges = this._containmentEdges;
  1060. var containmentEdgesLength = this._containmentEdges.length;
  1061.  
  1062. var flags = this._flags;
  1063. var flag = this._nodeFlags.pageObject;
  1064.  
  1065. var nodesToVisit = new Uint32Array(nodeCount);
  1066. var postOrderIndex2NodeOrdinal = new Uint32Array(nodeCount);
  1067. var nodeOrdinal2PostOrderIndex = new Uint32Array(nodeCount);
  1068. var painted = new Uint8Array(nodeCount);
  1069. var nodesToVisitLength = 0;
  1070. var postOrderIndex = 0;
  1071. var grey = 1;
  1072. var black = 2;
  1073.  
  1074. nodesToVisit[nodesToVisitLength++] = rootNodeOrdinal;
  1075. painted[rootNodeOrdinal] = grey;
  1076.  
  1077. while (nodesToVisitLength) {
  1078. var nodeOrdinal = nodesToVisit[nodesToVisitLength - 1];
  1079. if (painted[nodeOrdinal] === grey) {
  1080. painted[nodeOrdinal] = black;
  1081. var nodeFlag = flags[nodeOrdinal] & flag;
  1082. var beginEdgeIndex = firstEdgeIndexes[nodeOrdinal];
  1083. var endEdgeIndex = firstEdgeIndexes[nodeOrdinal + 1];
  1084. for (var edgeIndex = beginEdgeIndex; edgeIndex < endEdgeIndex; edgeIndex += edgeFieldsCount) {
  1085. if (nodeOrdinal !== rootNodeOrdinal && containmentEdges[edgeIndex + edgeTypeOffset] === edgeShortcutType)
  1086. continue;
  1087. var childNodeIndex = containmentEdges[edgeIndex + edgeToNodeOffset];
  1088. var childNodeOrdinal = childNodeIndex / nodeFieldCount;
  1089. var childNodeFlag = flags[childNodeOrdinal] & flag;
  1090.  
  1091.  
  1092. if (nodeOrdinal !== rootNodeOrdinal && childNodeFlag && !nodeFlag)
  1093. continue;
  1094. if (!painted[childNodeOrdinal]) {
  1095. painted[childNodeOrdinal] = grey;
  1096. nodesToVisit[nodesToVisitLength++] = childNodeOrdinal;
  1097. }
  1098. }
  1099. } else {
  1100. nodeOrdinal2PostOrderIndex[nodeOrdinal] = postOrderIndex;
  1101. postOrderIndex2NodeOrdinal[postOrderIndex++] = nodeOrdinal;
  1102. --nodesToVisitLength;
  1103. }
  1104. }
  1105.  
  1106. if (postOrderIndex !== nodeCount)
  1107. throw new Error("Postordering failed. " + (nodeCount - postOrderIndex) + " hanging nodes");
  1108.  
  1109. return {postOrderIndex2NodeOrdinal: postOrderIndex2NodeOrdinal, nodeOrdinal2PostOrderIndex: nodeOrdinal2PostOrderIndex};
  1110. },
  1111.  
  1112.  
  1113.  
  1114.  
  1115.  
  1116. _buildDominatorTree: function(postOrderIndex2NodeOrdinal, nodeOrdinal2PostOrderIndex)
  1117. {
  1118. var nodeFieldCount = this._nodeFieldCount;
  1119. var nodes = this._nodes;
  1120. var firstRetainerIndex = this._firstRetainerIndex;
  1121. var retainingNodes = this._retainingNodes;
  1122. var retainingEdges = this._retainingEdges;
  1123. var edgeFieldsCount = this._edgeFieldsCount;
  1124. var edgeTypeOffset = this._edgeTypeOffset;
  1125. var edgeToNodeOffset = this._edgeToNodeOffset;
  1126. var edgeShortcutType = this._edgeShortcutType;
  1127. var firstEdgeIndexes = this._firstEdgeIndexes;
  1128. var containmentEdges = this._containmentEdges;
  1129. var containmentEdgesLength = this._containmentEdges.length;
  1130. var rootNodeIndex = this._rootNodeIndex;
  1131.  
  1132. var flags = this._flags;
  1133. var flag = this._nodeFlags.pageObject;
  1134.  
  1135. var nodesCount = postOrderIndex2NodeOrdinal.length;
  1136. var rootPostOrderedIndex = nodesCount - 1;
  1137. var noEntry = nodesCount;
  1138. var dominators = new Uint32Array(nodesCount);
  1139. for (var i = 0; i < rootPostOrderedIndex; ++i)
  1140. dominators[i] = noEntry;
  1141. dominators[rootPostOrderedIndex] = rootPostOrderedIndex;
  1142.  
  1143.  
  1144.  
  1145. var affected = new Uint8Array(nodesCount);
  1146. var nodeOrdinal;
  1147.  
  1148. nodeOrdinal = this._rootNodeIndex / nodeFieldCount;
  1149. var beginEdgeToNodeFieldIndex = firstEdgeIndexes[nodeOrdinal] + edgeToNodeOffset;
  1150. var endEdgeToNodeFieldIndex = firstEdgeIndexes[nodeOrdinal + 1];
  1151. for (var toNodeFieldIndex = beginEdgeToNodeFieldIndex;
  1152. toNodeFieldIndex < endEdgeToNodeFieldIndex;
  1153. toNodeFieldIndex += edgeFieldsCount) {
  1154. var childNodeOrdinal = containmentEdges[toNodeFieldIndex] / nodeFieldCount;
  1155. affected[nodeOrdinal2PostOrderIndex[childNodeOrdinal]] = 1;
  1156. }
  1157. }
  1158.  
  1159. var changed = true;
  1160. while (changed) {
  1161. changed = false;
  1162. for (var postOrderIndex = rootPostOrderedIndex - 1; postOrderIndex >= 0; --postOrderIndex) {
  1163. if (affected[postOrderIndex] === 0)
  1164. continue;
  1165. affected[postOrderIndex] = 0;
  1166.  
  1167.  
  1168. if (dominators[postOrderIndex] === rootPostOrderedIndex)
  1169. continue;
  1170. nodeOrdinal = postOrderIndex2NodeOrdinal[postOrderIndex];
  1171. var nodeFlag = !!(flags[nodeOrdinal] & flag);
  1172. var newDominatorIndex = noEntry;
  1173. var beginRetainerIndex = firstRetainerIndex[nodeOrdinal];
  1174. var endRetainerIndex = firstRetainerIndex[nodeOrdinal + 1];
  1175. for (var retainerIndex = beginRetainerIndex; retainerIndex < endRetainerIndex; ++retainerIndex) {
  1176. var retainerEdgeIndex = retainingEdges[retainerIndex];
  1177. var retainerEdgeType = containmentEdges[retainerEdgeIndex + edgeTypeOffset];
  1178. var retainerNodeIndex = retainingNodes[retainerIndex];
  1179. if (retainerNodeIndex !== rootNodeIndex && retainerEdgeType === edgeShortcutType)
  1180. continue;
  1181. var retainerNodeOrdinal = retainerNodeIndex / nodeFieldCount;
  1182. var retainerNodeFlag = !!(flags[retainerNodeOrdinal] & flag);
  1183.  
  1184.  
  1185. if (retainerNodeIndex !== rootNodeIndex && nodeFlag && !retainerNodeFlag)
  1186. continue;
  1187. var retanerPostOrderIndex = nodeOrdinal2PostOrderIndex[retainerNodeOrdinal];
  1188. if (dominators[retanerPostOrderIndex] !== noEntry) {
  1189. if (newDominatorIndex === noEntry)
  1190. newDominatorIndex = retanerPostOrderIndex;
  1191. else {
  1192. while (retanerPostOrderIndex !== newDominatorIndex) {
  1193. while (retanerPostOrderIndex < newDominatorIndex)
  1194. retanerPostOrderIndex = dominators[retanerPostOrderIndex];
  1195. while (newDominatorIndex < retanerPostOrderIndex)
  1196. newDominatorIndex = dominators[newDominatorIndex];
  1197. }
  1198. }
  1199.  
  1200.  
  1201. if (newDominatorIndex === rootPostOrderedIndex)
  1202. break;
  1203. }
  1204. }
  1205. if (newDominatorIndex !== noEntry && dominators[postOrderIndex] !== newDominatorIndex) {
  1206. dominators[postOrderIndex] = newDominatorIndex;
  1207. changed = true;
  1208. nodeOrdinal = postOrderIndex2NodeOrdinal[postOrderIndex];
  1209. beginEdgeToNodeFieldIndex = firstEdgeIndexes[nodeOrdinal] + edgeToNodeOffset;
  1210. endEdgeToNodeFieldIndex = firstEdgeIndexes[nodeOrdinal + 1];
  1211. for (var toNodeFieldIndex = beginEdgeToNodeFieldIndex;
  1212. toNodeFieldIndex < endEdgeToNodeFieldIndex;
  1213. toNodeFieldIndex += edgeFieldsCount) {
  1214. var childNodeOrdinal = containmentEdges[toNodeFieldIndex] / nodeFieldCount;
  1215. affected[nodeOrdinal2PostOrderIndex[childNodeOrdinal]] = 1;
  1216. }
  1217. }
  1218. }
  1219. }
  1220.  
  1221. var dominatorsTree = new Uint32Array(nodesCount);
  1222. for (var postOrderIndex = 0, l = dominators.length; postOrderIndex < l; ++postOrderIndex) {
  1223. nodeOrdinal = postOrderIndex2NodeOrdinal[postOrderIndex];
  1224. dominatorsTree[nodeOrdinal] = postOrderIndex2NodeOrdinal[dominators[postOrderIndex]];
  1225. }
  1226. return dominatorsTree;
  1227. },
  1228.  
  1229. _calculateRetainedSizes: function(postOrderIndex2NodeOrdinal)
  1230. {
  1231. var nodeCount = this.nodeCount;
  1232. var nodes = this._nodes;
  1233. var nodeSelfSizeOffset = this._nodeSelfSizeOffset;
  1234. var nodeFieldCount = this._nodeFieldCount;
  1235. var dominatorsTree = this._dominatorsTree;
  1236.  
  1237. var nodeRetainedSizeOffset = this._nodeRetainedSizeOffset = this._nodeEdgeCountOffset;
  1238. delete this._nodeEdgeCountOffset;
  1239.  
  1240. for (var nodeIndex = 0, l = nodes.length; nodeIndex < l; nodeIndex += nodeFieldCount)
  1241. nodes[nodeIndex + nodeRetainedSizeOffset] = nodes[nodeIndex + nodeSelfSizeOffset];
  1242.  
  1243.  
  1244. for (var postOrderIndex = 0; postOrderIndex < nodeCount - 1; ++postOrderIndex) {
  1245. var nodeOrdinal = postOrderIndex2NodeOrdinal[postOrderIndex];
  1246. var nodeIndex = nodeOrdinal * nodeFieldCount;
  1247. var dominatorIndex = dominatorsTree[nodeOrdinal] * nodeFieldCount;
  1248. nodes[dominatorIndex + nodeRetainedSizeOffset] += nodes[nodeIndex + nodeRetainedSizeOffset];
  1249. }
  1250. },
  1251.  
  1252. _buildDominatedNodes: function()
  1253. {
  1254.  
  1255.  
  1256.  
  1257.  
  1258.  
  1259. var indexArray = this._firstDominatedNodeIndex = new Uint32Array(this.nodeCount + 1);
  1260.  
  1261. var dominatedNodes = this._dominatedNodes = new Uint32Array(this.nodeCount - 1);
  1262.  
  1263.  
  1264.  
  1265. var nodeFieldCount = this._nodeFieldCount;
  1266. var dominatorsTree = this._dominatorsTree;
  1267. for (var nodeOrdinal = 1, l = this.nodeCount; nodeOrdinal < l; ++nodeOrdinal)
  1268. ++indexArray[dominatorsTree[nodeOrdinal]];
  1269.  
  1270.  
  1271. var firstDominatedNodeIndex = 0;
  1272. for (var i = 0, l = this.nodeCount; i < l; ++i) {
  1273. var dominatedCount = dominatedNodes[firstDominatedNodeIndex] = indexArray[i];
  1274. indexArray[i] = firstDominatedNodeIndex;
  1275. firstDominatedNodeIndex += dominatedCount;
  1276. }
  1277. indexArray[this.nodeCount] = dominatedNodes.length;
  1278.  
  1279.  
  1280. for (var nodeOrdinal = 1, l = this.nodeCount; nodeOrdinal < l; ++nodeOrdinal) {
  1281. var dominatorOrdinal = dominatorsTree[nodeOrdinal];
  1282. var dominatedRefIndex = indexArray[dominatorOrdinal];
  1283. dominatedRefIndex += (--dominatedNodes[dominatedRefIndex]);
  1284. dominatedNodes[dominatedRefIndex] = nodeOrdinal * nodeFieldCount;
  1285. }
  1286. },
  1287.  
  1288. _markInvisibleEdges: function()
  1289. {
  1290.  
  1291.  
  1292.  
  1293. for (var iter = this.rootNode().edges(); iter.hasNext(); iter.next()) {
  1294. var edge = iter.edge;
  1295. if (!edge.isShortcut())
  1296. continue;
  1297. var node = edge.node();
  1298. var propNames = {};
  1299. for (var innerIter = node.edges(); innerIter.hasNext(); innerIter.next()) {
  1300. var globalObjEdge = innerIter.edge;
  1301. if (globalObjEdge.isShortcut())
  1302. propNames[globalObjEdge._nameOrIndex()] = true;
  1303. }
  1304. for (innerIter.first(); innerIter.hasNext(); innerIter.next()) {
  1305. var globalObjEdge = innerIter.edge;
  1306. if (!globalObjEdge.isShortcut()
  1307. && globalObjEdge.node().isHidden()
  1308. && globalObjEdge._hasStringName()
  1309. && (globalObjEdge._nameOrIndex() in propNames))
  1310. this._containmentEdges[globalObjEdge._edges._start + globalObjEdge.edgeIndex + this._edgeTypeOffset] = this._edgeInvisibleType;
  1311. }
  1312. }
  1313. },
  1314.  
  1315. _numbersComparator: function(a, b)
  1316. {
  1317. return a < b ? -1 : (a > b ? 1 : 0);
  1318. },
  1319.  
  1320. _markDetachedDOMTreeNodes: function()
  1321. {
  1322. var flag = this._nodeFlags.detachedDOMTreeNode;
  1323. var detachedDOMTreesRoot;
  1324. for (var iter = this.rootNode().edges(); iter.hasNext(); iter.next()) {
  1325. var node = iter.edge.node();
  1326. if (node.isDetachedDOMTreesRoot()) {
  1327. detachedDOMTreesRoot = node;
  1328. break;
  1329. }
  1330. }
  1331.  
  1332. if (!detachedDOMTreesRoot)
  1333. return;
  1334.  
  1335. for (var iter = detachedDOMTreesRoot.edges(); iter.hasNext(); iter.next()) {
  1336. var node = iter.edge.node();
  1337. if (node.isDetachedDOMTree()) {
  1338. for (var edgesIter = node.edges(); edgesIter.hasNext(); edgesIter.next())
  1339. this._flags[edgesIter.edge.node().nodeIndex / this._nodeFieldCount] |= flag;
  1340. }
  1341. }
  1342. },
  1343.  
  1344. _markPageOwnedNodes: function()
  1345. {
  1346. var edgeShortcutType = this._edgeShortcutType;
  1347. var edgeToNodeOffset = this._edgeToNodeOffset;
  1348. var edgeTypeOffset = this._edgeTypeOffset;
  1349. var edgeFieldsCount = this._edgeFieldsCount;
  1350. var edgeWeakType = this._edgeWeakType;
  1351. var firstEdgeIndexes = this._firstEdgeIndexes;
  1352. var containmentEdges = this._containmentEdges;
  1353. var containmentEdgesLength = containmentEdges.length;
  1354. var nodes = this._nodes;
  1355. var nodeFieldCount = this._nodeFieldCount;
  1356. var nodesCount = this.nodeCount;
  1357.  
  1358. var flags = this._flags;
  1359. var flag = this._nodeFlags.pageObject;
  1360. var visitedMarker = this._nodeFlags.visitedMarker;
  1361. var visitedMarkerMask = this._nodeFlags.visitedMarkerMask;
  1362. var markerAndFlag = visitedMarker | flag;
  1363.  
  1364. var nodesToVisit = new Uint32Array(nodesCount);
  1365. var nodesToVisitLength = 0;
  1366.  
  1367. var rootNodeOrdinal = this._rootNodeIndex / nodeFieldCount;
  1368. for (var edgeIndex = firstEdgeIndexes[rootNodeOrdinal], endEdgeIndex = firstEdgeIndexes[rootNodeOrdinal + 1];
  1369. edgeIndex < endEdgeIndex;
  1370. edgeIndex += edgeFieldsCount) {
  1371. if (containmentEdges[edgeIndex + edgeTypeOffset] === edgeShortcutType) {
  1372. var nodeOrdinal = containmentEdges[edgeIndex + edgeToNodeOffset] / nodeFieldCount;
  1373. nodesToVisit[nodesToVisitLength++] = nodeOrdinal;
  1374. flags[nodeOrdinal] |= visitedMarker;
  1375. }
  1376. }
  1377.  
  1378. while (nodesToVisitLength) {
  1379. var nodeOrdinal = nodesToVisit[--nodesToVisitLength];
  1380. flags[nodeOrdinal] |= flag;
  1381. flags[nodeOrdinal] &= visitedMarkerMask;
  1382. var beginEdgeIndex = firstEdgeIndexes[nodeOrdinal];
  1383. var endEdgeIndex = firstEdgeIndexes[nodeOrdinal + 1];
  1384. for (var edgeIndex = beginEdgeIndex; edgeIndex < endEdgeIndex; edgeIndex += edgeFieldsCount) {
  1385. var childNodeIndex = containmentEdges[edgeIndex + edgeToNodeOffset];
  1386. var childNodeOrdinal = childNodeIndex / nodeFieldCount;
  1387. if (flags[childNodeOrdinal] & markerAndFlag)
  1388. continue;
  1389. var type = containmentEdges[edgeIndex + edgeTypeOffset];
  1390. if (type === edgeWeakType)
  1391. continue;
  1392. nodesToVisit[nodesToVisitLength++] = childNodeOrdinal;
  1393. flags[childNodeOrdinal] |= visitedMarker;
  1394. }
  1395. }
  1396. },
  1397.  
  1398. _markQueriableHeapObjects: function()
  1399. {
  1400.  
  1401.  
  1402.  
  1403. var flag = this._nodeFlags.canBeQueried;
  1404. var hiddenEdgeType = this._edgeHiddenType;
  1405. var internalEdgeType = this._edgeInternalType;
  1406. var invisibleEdgeType = this._edgeInvisibleType;
  1407. var weakEdgeType = this._edgeWeakType;
  1408. var edgeToNodeOffset = this._edgeToNodeOffset;
  1409. var edgeTypeOffset = this._edgeTypeOffset;
  1410. var edgeFieldsCount = this._edgeFieldsCount;
  1411. var containmentEdges = this._containmentEdges;
  1412. var nodes = this._nodes;
  1413. var nodeCount = this.nodeCount;
  1414. var nodeFieldCount = this._nodeFieldCount;
  1415. var firstEdgeIndexes = this._firstEdgeIndexes;
  1416.  
  1417. var flags = this._flags;
  1418. var list = [];
  1419.  
  1420. for (var iter = this.rootNode().edges(); iter.hasNext(); iter.next()) {
  1421. if (iter.edge.node().isWindow())
  1422. list.push(iter.edge.node().nodeIndex / nodeFieldCount);
  1423. }
  1424.  
  1425. while (list.length) {
  1426. var nodeOrdinal = list.pop();
  1427. if (flags[nodeOrdinal] & flag)
  1428. continue;
  1429. flags[nodeOrdinal] |= flag;
  1430. var beginEdgeIndex = firstEdgeIndexes[nodeOrdinal];
  1431. var endEdgeIndex = firstEdgeIndexes[nodeOrdinal + 1];
  1432. for (var edgeIndex = beginEdgeIndex; edgeIndex < endEdgeIndex; edgeIndex += edgeFieldsCount) {
  1433. var childNodeIndex = containmentEdges[edgeIndex + edgeToNodeOffset];
  1434. var childNodeOrdinal = childNodeIndex / nodeFieldCount;
  1435. if (flags[childNodeOrdinal] & flag)
  1436. continue;
  1437. var type = containmentEdges[edgeIndex + edgeTypeOffset];
  1438. if (type === hiddenEdgeType || type === invisibleEdgeType || type === internalEdgeType || type === weakEdgeType)
  1439. continue;
  1440. list.push(childNodeOrdinal);
  1441. }
  1442. }
  1443. },
  1444.  
  1445. _calculateFlags: function()
  1446. {
  1447. this._flags = new Uint32Array(this.nodeCount);
  1448. this._markDetachedDOMTreeNodes();
  1449. this._markQueriableHeapObjects();
  1450. this._markPageOwnedNodes();
  1451. },
  1452.  
  1453. calculateSnapshotDiff: function(baseSnapshotId, baseSnapshotAggregates)
  1454. {
  1455. var snapshotDiff = this._snapshotDiffs[baseSnapshotId];
  1456. if (snapshotDiff)
  1457. return snapshotDiff;
  1458. snapshotDiff = {};
  1459.  
  1460. var aggregates = this.aggregates(true, "allObjects");
  1461. for (var className in baseSnapshotAggregates) {
  1462. var baseAggregate = baseSnapshotAggregates[className];
  1463. var diff = this._calculateDiffForClass(baseAggregate, aggregates[className]);
  1464. if (diff)
  1465. snapshotDiff[className] = diff;
  1466. }
  1467. var emptyBaseAggregate = { ids: [], indexes: [], selfSizes: [] };
  1468. for (var className in aggregates) {
  1469. if (className in baseSnapshotAggregates)
  1470. continue;
  1471. snapshotDiff[className] = this._calculateDiffForClass(emptyBaseAggregate, aggregates[className]);
  1472. }
  1473.  
  1474. this._snapshotDiffs[baseSnapshotId] = snapshotDiff;
  1475. return snapshotDiff;
  1476. },
  1477.  
  1478. _calculateDiffForClass: function(baseAggregate, aggregate)
  1479. {
  1480. var baseIds = baseAggregate.ids;
  1481. var baseIndexes = baseAggregate.indexes;
  1482. var baseSelfSizes = baseAggregate.selfSizes;
  1483.  
  1484. var indexes = aggregate ? aggregate.idxs : [];
  1485.  
  1486. var i = 0, l = baseIds.length;
  1487. var j = 0, m = indexes.length;
  1488. var diff = { addedCount: 0,
  1489. removedCount: 0,
  1490. addedSize: 0,
  1491. removedSize: 0,
  1492. deletedIndexes: [],
  1493. addedIndexes: [] };
  1494.  
  1495. var nodeB = new WebInspector.HeapSnapshotNode(this, indexes[j]);
  1496. while (i < l && j < m) {
  1497. var nodeAId = baseIds[i];
  1498. if (nodeAId < nodeB.id()) {
  1499. diff.deletedIndexes.push(baseIndexes[i]);
  1500. diff.removedCount++;
  1501. diff.removedSize += baseSelfSizes[i];
  1502. ++i;
  1503. } else if (nodeAId > nodeB.id()) { 
  1504. diff.addedIndexes.push(indexes[j]);
  1505. diff.addedCount++;
  1506. diff.addedSize += nodeB.selfSize();
  1507. nodeB.nodeIndex = indexes[++j];
  1508. } else { 
  1509. ++i;
  1510. nodeB.nodeIndex = indexes[++j];
  1511. }
  1512. }
  1513. while (i < l) {
  1514. diff.deletedIndexes.push(baseIndexes[i]);
  1515. diff.removedCount++;
  1516. diff.removedSize += baseSelfSizes[i];
  1517. ++i;
  1518. }
  1519. while (j < m) {
  1520. diff.addedIndexes.push(indexes[j]);
  1521. diff.addedCount++;
  1522. diff.addedSize += nodeB.selfSize();
  1523. nodeB.nodeIndex = indexes[++j];
  1524. }
  1525. diff.countDelta = diff.addedCount - diff.removedCount;
  1526. diff.sizeDelta = diff.addedSize - diff.removedSize;
  1527. if (!diff.addedCount && !diff.removedCount)
  1528. return null;
  1529. return diff;
  1530. },
  1531.  
  1532. _nodeForSnapshotObjectId: function(snapshotObjectId)
  1533. {
  1534. for (var it = this._allNodes(); it.hasNext(); it.next()) {
  1535. if (it.node.id() === snapshotObjectId)
  1536. return it.node;
  1537. }
  1538. return null;
  1539. },
  1540.  
  1541. nodeClassName: function(snapshotObjectId)
  1542. {
  1543. var node = this._nodeForSnapshotObjectId(snapshotObjectId);
  1544. if (node)
  1545. return node.className();
  1546. return null;
  1547. },
  1548.  
  1549. dominatorIdsForNode: function(snapshotObjectId)
  1550. {
  1551. var node = this._nodeForSnapshotObjectId(snapshotObjectId);
  1552. if (!node)
  1553. return null;
  1554. var result = [];
  1555. while (!node.isRoot()) {
  1556. result.push(node.id());
  1557. node.nodeIndex = node.dominatorIndex();
  1558. }
  1559. return result;
  1560. },
  1561.  
  1562. _parseFilter: function(filter)
  1563. {
  1564. if (!filter)
  1565. return null;
  1566. var parsedFilter = eval("(function(){return " + filter + "})()");
  1567. return parsedFilter.bind(this);
  1568. },
  1569.  
  1570. createEdgesProvider: function(nodeIndex, filter)
  1571. {
  1572. var node = new WebInspector.HeapSnapshotNode(this, nodeIndex);
  1573. return new WebInspector.HeapSnapshotEdgesProvider(this, this._parseFilter(filter), node.edges());
  1574. },
  1575.  
  1576. createRetainingEdgesProvider: function(nodeIndex, filter)
  1577. {
  1578. var node = new WebInspector.HeapSnapshotNode(this, nodeIndex);
  1579. return new WebInspector.HeapSnapshotEdgesProvider(this, this._parseFilter(filter), node.retainers());
  1580. },
  1581.  
  1582. createAddedNodesProvider: function(baseSnapshotId, className)
  1583. {
  1584. var snapshotDiff = this._snapshotDiffs[baseSnapshotId];
  1585. var diffForClass = snapshotDiff[className];
  1586. return new WebInspector.HeapSnapshotNodesProvider(this, null, diffForClass.addedIndexes);
  1587. },
  1588.  
  1589. createDeletedNodesProvider: function(nodeIndexes)
  1590. {
  1591. return new WebInspector.HeapSnapshotNodesProvider(this, null, nodeIndexes);
  1592. },
  1593.  
  1594. createNodesProviderForClass: function(className, aggregatesKey)
  1595. {
  1596. function filter(node) {
  1597. return node.isPageObject();
  1598. }
  1599. return new WebInspector.HeapSnapshotNodesProvider(this, filter, this.aggregates(false, aggregatesKey)[className].idxs);
  1600. },
  1601.  
  1602. createNodesProviderForDominator: function(nodeIndex)
  1603. {
  1604. var node = new WebInspector.HeapSnapshotNode(this, nodeIndex);
  1605. return new WebInspector.HeapSnapshotNodesProvider(this, null, this._dominatedNodesOfNode(node));
  1606. },
  1607.  
  1608. updateStaticData: function()
  1609. {
  1610. return {nodeCount: this.nodeCount, rootNodeIndex: this._rootNodeIndex, totalSize: this.totalSize, uid: this.uid, nodeFlags: this._nodeFlags};
  1611. }
  1612. };
  1613.  
  1614.  
  1615. WebInspector.HeapSnapshotFilteredOrderedIterator = function(iterator, filter, unfilteredIterationOrder)
  1616. {
  1617. this._filter = filter;
  1618. this._iterator = iterator;
  1619. this._unfilteredIterationOrder = unfilteredIterationOrder;
  1620. this._iterationOrder = null;
  1621. this._position = 0;
  1622. this._currentComparator = null;
  1623. this._sortedPrefixLength = 0;
  1624. }
  1625.  
  1626. WebInspector.HeapSnapshotFilteredOrderedIterator.prototype = {
  1627. _createIterationOrder: function()
  1628. {
  1629. if (this._iterationOrder)
  1630. return;
  1631. if (this._unfilteredIterationOrder && !this._filter) {
  1632. this._iterationOrder = this._unfilteredIterationOrder.slice(0);
  1633. this._unfilteredIterationOrder = null;
  1634. return;
  1635. }
  1636. this._iterationOrder = [];
  1637. var iterator = this._iterator;
  1638. if (!this._unfilteredIterationOrder && !this._filter) {
  1639. for (iterator.first(); iterator.hasNext(); iterator.next())
  1640. this._iterationOrder.push(iterator.index());
  1641. } else if (!this._unfilteredIterationOrder) {
  1642. for (iterator.first(); iterator.hasNext(); iterator.next()) {
  1643. if (this._filter(iterator.item()))
  1644. this._iterationOrder.push(iterator.index());
  1645. }
  1646. } else {
  1647. var order = this._unfilteredIterationOrder.constructor === Array ?
  1648. this._unfilteredIterationOrder : this._unfilteredIterationOrder.slice(0);
  1649. for (var i = 0, l = order.length; i < l; ++i) {
  1650. iterator.setIndex(order[i]);
  1651. if (this._filter(iterator.item()))
  1652. this._iterationOrder.push(iterator.index());
  1653. }
  1654. this._unfilteredIterationOrder = null;
  1655. }
  1656. },
  1657.  
  1658. first: function()
  1659. {
  1660. this._position = 0;
  1661. },
  1662.  
  1663. hasNext: function()
  1664. {
  1665. return this._position < this._iterationOrder.length;
  1666. },
  1667.  
  1668. isEmpty: function()
  1669. {
  1670. if (this._iterationOrder)
  1671. return !this._iterationOrder.length;
  1672. if (this._unfilteredIterationOrder && !this._filter)
  1673. return !this._unfilteredIterationOrder.length;
  1674. var iterator = this._iterator;
  1675. if (!this._unfilteredIterationOrder && !this._filter) {
  1676. iterator.first();
  1677. return !iterator.hasNext();
  1678. } else if (!this._unfilteredIterationOrder) {
  1679. for (iterator.first(); iterator.hasNext(); iterator.next())
  1680. if (this._filter(iterator.item()))
  1681. return false;
  1682. } else {
  1683. var order = this._unfilteredIterationOrder.constructor === Array ?
  1684. this._unfilteredIterationOrder : this._unfilteredIterationOrder.slice(0);
  1685. for (var i = 0, l = order.length; i < l; ++i) {
  1686. iterator.setIndex(order[i]);
  1687. if (this._filter(iterator.item()))
  1688. return false;
  1689. }
  1690. }
  1691. return true;
  1692. },
  1693.  
  1694. item: function()
  1695. {
  1696. this._iterator.setIndex(this._iterationOrder[this._position]);
  1697. return this._iterator.item();
  1698. },
  1699.  
  1700. get length()
  1701. {
  1702. this._createIterationOrder();
  1703. return this._iterationOrder.length;
  1704. },
  1705.  
  1706. next: function()
  1707. {
  1708. ++this._position;
  1709. },
  1710.  
  1711.  
  1712. serializeItemsRange: function(begin, end)
  1713. {
  1714. this._createIterationOrder();
  1715. if (begin > end)
  1716. throw new Error("Start position > end position: " + begin + " > " + end);
  1717. if (end >= this._iterationOrder.length)
  1718. end = this._iterationOrder.length;
  1719. if (this._sortedPrefixLength < end) {
  1720. this.sort(this._currentComparator, this._sortedPrefixLength, this._iterationOrder.length - 1, end - this._sortedPrefixLength);
  1721. this._sortedPrefixLength = end;
  1722. }
  1723.  
  1724. this._position = begin;
  1725. var startPosition = this._position;
  1726. var count = end - begin;
  1727. var result = new Array(count);
  1728. for (var i = 0 ; i < count && this.hasNext(); ++i, this.next())
  1729. result[i] = this.serializeItem(this.item());
  1730. result.length = i;
  1731. result.totalLength = this._iterationOrder.length;
  1732.  
  1733. result.startPosition = startPosition;
  1734. result.endPosition = this._position;
  1735. return result;
  1736. },
  1737.  
  1738. sortAll: function()
  1739. {
  1740. this._createIterationOrder();
  1741. if (this._sortedPrefixLength === this._iterationOrder.length)
  1742. return;
  1743. this.sort(this._currentComparator, this._sortedPrefixLength, this._iterationOrder.length - 1, this._iterationOrder.length);
  1744. this._sortedPrefixLength = this._iterationOrder.length;
  1745. },
  1746.  
  1747. sortAndRewind: function(comparator)
  1748. {
  1749. this._currentComparator = comparator;
  1750. this._sortedPrefixLength = 0;
  1751. this.first();
  1752. }
  1753. }
  1754.  
  1755. WebInspector.HeapSnapshotFilteredOrderedIterator.prototype.createComparator = function(fieldNames)
  1756. {
  1757. return {fieldName1:fieldNames[0], ascending1:fieldNames[1], fieldName2:fieldNames[2], ascending2:fieldNames[3]};
  1758. }
  1759.  
  1760.  
  1761. WebInspector.HeapSnapshotEdgesProvider = function(snapshot, filter, edgesIter)
  1762. {
  1763. this.snapshot = snapshot;
  1764. WebInspector.HeapSnapshotFilteredOrderedIterator.call(this, edgesIter, filter);
  1765. }
  1766.  
  1767. WebInspector.HeapSnapshotEdgesProvider.prototype = {
  1768. serializeItem: function(edge)
  1769. {
  1770. return {
  1771. name: edge.name(),
  1772. propertyAccessor: edge.toString(),
  1773. node: WebInspector.HeapSnapshotNodesProvider.prototype.serializeItem(edge.node()),
  1774. nodeIndex: edge.nodeIndex(),
  1775. type: edge.type(),
  1776. distanceToWindow: edge.node().distanceToWindow()
  1777. };
  1778. },
  1779.  
  1780. sort: function(comparator, leftBound, rightBound, count)
  1781. {
  1782. var fieldName1 = comparator.fieldName1;
  1783. var fieldName2 = comparator.fieldName2;
  1784. var ascending1 = comparator.ascending1;
  1785. var ascending2 = comparator.ascending2;
  1786.  
  1787. var edgeA = this._iterator.item().clone();
  1788. var edgeB = edgeA.clone();
  1789. var nodeA = new WebInspector.HeapSnapshotNode(this.snapshot);
  1790. var nodeB = new WebInspector.HeapSnapshotNode(this.snapshot);
  1791.  
  1792. function compareEdgeFieldName(ascending, indexA, indexB)
  1793. {
  1794. edgeA.edgeIndex = indexA;
  1795. edgeB.edgeIndex = indexB;
  1796. if (edgeB.name() === "__proto__") return -1;
  1797. if (edgeA.name() === "__proto__") return 1;
  1798. var result =
  1799. edgeA.hasStringName() === edgeB.hasStringName() ?
  1800. (edgeA.name() < edgeB.name() ? -1 : (edgeA.name() > edgeB.name() ? 1 : 0)) :
  1801. (edgeA.hasStringName() ? -1 : 1);
  1802. return ascending ? result : -result;
  1803. }
  1804.  
  1805. function compareNodeField(fieldName, ascending, indexA, indexB)
  1806. {
  1807. edgeA.edgeIndex = indexA;
  1808. nodeA.nodeIndex = edgeA.nodeIndex();
  1809. var valueA = nodeA[fieldName]();
  1810.  
  1811. edgeB.edgeIndex = indexB;
  1812. nodeB.nodeIndex = edgeB.nodeIndex();
  1813. var valueB = nodeB[fieldName]();
  1814.  
  1815. var result = valueA < valueB ? -1 : (valueA > valueB ? 1 : 0);
  1816. return ascending ? result : -result;
  1817. }
  1818.  
  1819. function compareEdgeAndNode(indexA, indexB) {
  1820. var result = compareEdgeFieldName(ascending1, indexA, indexB);
  1821. if (result === 0)
  1822. result = compareNodeField(fieldName2, ascending2, indexA, indexB);
  1823. return result;
  1824. }
  1825.  
  1826. function compareNodeAndEdge(indexA, indexB) {
  1827. var result = compareNodeField(fieldName1, ascending1, indexA, indexB);
  1828. if (result === 0)
  1829. result = compareEdgeFieldName(ascending2, indexA, indexB);
  1830. return result;
  1831. }
  1832.  
  1833. function compareNodeAndNode(indexA, indexB) {
  1834. var result = compareNodeField(fieldName1, ascending1, indexA, indexB);
  1835. if (result === 0)
  1836. result = compareNodeField(fieldName2, ascending2, indexA, indexB);
  1837. return result;
  1838. }
  1839.  
  1840. if (fieldName1 === "!edgeName")
  1841. this._iterationOrder.sortRange(compareEdgeAndNode, leftBound, rightBound, count);
  1842. else if (fieldName2 === "!edgeName")
  1843. this._iterationOrder.sortRange(compareNodeAndEdge, leftBound, rightBound, count);
  1844. else
  1845. this._iterationOrder.sortRange(compareNodeAndNode, leftBound, rightBound, count);
  1846. },
  1847.  
  1848. __proto__: WebInspector.HeapSnapshotFilteredOrderedIterator.prototype
  1849. }
  1850.  
  1851.  
  1852.  
  1853. WebInspector.HeapSnapshotNodesProvider = function(snapshot, filter, nodeIndexes)
  1854. {
  1855. this.snapshot = snapshot;
  1856. WebInspector.HeapSnapshotFilteredOrderedIterator.call(this, snapshot._allNodes(), filter, nodeIndexes);
  1857. }
  1858.  
  1859. WebInspector.HeapSnapshotNodesProvider.prototype = {
  1860. nodePosition: function(snapshotObjectId)
  1861. {
  1862. this._createIterationOrder();
  1863. if (this.isEmpty())
  1864. return -1;
  1865. this.sortAll();
  1866.  
  1867. var node = new WebInspector.HeapSnapshotNode(this.snapshot);
  1868. for (var i = 0; i < this._iterationOrder.length; i++) {
  1869. node.nodeIndex = this._iterationOrder[i];
  1870. if (node.id() === snapshotObjectId)
  1871. return i;
  1872. }
  1873. return -1;
  1874. },
  1875.  
  1876. serializeItem: function(node)
  1877. {
  1878. return {
  1879. id: node.id(),
  1880. name: node.name(),
  1881. distanceToWindow: node.distanceToWindow(),
  1882. nodeIndex: node.nodeIndex,
  1883. retainedSize: node.retainedSize(),
  1884. selfSize: node.selfSize(),
  1885. type: node.type(),
  1886. flags: node.flags()
  1887. };
  1888. },
  1889.  
  1890. sort: function(comparator, leftBound, rightBound, count)
  1891. {
  1892. var fieldName1 = comparator.fieldName1;
  1893. var fieldName2 = comparator.fieldName2;
  1894. var ascending1 = comparator.ascending1;
  1895. var ascending2 = comparator.ascending2;
  1896.  
  1897. var nodeA = new WebInspector.HeapSnapshotNode(this.snapshot);
  1898. var nodeB = new WebInspector.HeapSnapshotNode(this.snapshot);
  1899.  
  1900. function sortByNodeField(fieldName, ascending)
  1901. {
  1902. var valueOrFunctionA = nodeA[fieldName];
  1903. var valueA = typeof valueOrFunctionA !== "function" ? valueOrFunctionA : valueOrFunctionA.call(nodeA);
  1904. var valueOrFunctionB = nodeB[fieldName];
  1905. var valueB = typeof valueOrFunctionB !== "function" ? valueOrFunctionB : valueOrFunctionB.call(nodeB);
  1906. var result = valueA < valueB ? -1 : (valueA > valueB ? 1 : 0);
  1907. return ascending ? result : -result;
  1908. }
  1909.  
  1910. function sortByComparator(indexA, indexB) {
  1911. nodeA.nodeIndex = indexA;
  1912. nodeB.nodeIndex = indexB;
  1913. var result = sortByNodeField(fieldName1, ascending1);
  1914. if (result === 0)
  1915. result = sortByNodeField(fieldName2, ascending2);
  1916. return result;
  1917. }
  1918.  
  1919. this._iterationOrder.sortRange(sortByComparator, leftBound, rightBound, count);
  1920. },
  1921.  
  1922. __proto__: WebInspector.HeapSnapshotFilteredOrderedIterator.prototype
  1923. }
  1924.  
  1925. ;
  1926.  
  1927.  
  1928.  
  1929. WebInspector.HeapSnapshotLoader = function()
  1930. {
  1931. this._reset();
  1932. }
  1933.  
  1934. WebInspector.HeapSnapshotLoader.prototype = {
  1935. dispose: function()
  1936. {
  1937. this._reset();
  1938. },
  1939.  
  1940. _reset: function()
  1941. {
  1942. this._json = "";
  1943. this._state = "find-snapshot-info";
  1944. this._snapshot = {};
  1945. },
  1946.  
  1947. close: function()
  1948. {
  1949. if (this._json)
  1950. this._parseStringsArray();
  1951. },
  1952.  
  1953. buildSnapshot: function()
  1954. {
  1955. var result = new WebInspector.HeapSnapshot(this._snapshot);
  1956. this._reset();
  1957. return result;
  1958. },
  1959.  
  1960. _parseUintArray: function()
  1961. {
  1962. var index = 0;
  1963. var char0 = "0".charCodeAt(0), char9 = "9".charCodeAt(0), closingBracket = "]".charCodeAt(0);
  1964. var length = this._json.length;
  1965. while (true) {
  1966. while (index < length) {
  1967. var code = this._json.charCodeAt(index);
  1968. if (char0 <= code && code <= char9)
  1969. break;
  1970. else if (code === closingBracket) {
  1971. this._json = this._json.slice(index + 1);
  1972. return false;
  1973. }
  1974. ++index;
  1975. }
  1976. if (index === length) {
  1977. this._json = "";
  1978. return true;
  1979. }
  1980. var nextNumber = 0;
  1981. var startIndex = index;
  1982. while (index < length) {
  1983. var code = this._json.charCodeAt(index);
  1984. if (char0 > code || code > char9)
  1985. break;
  1986. nextNumber *= 10;
  1987. nextNumber += (code - char0);
  1988. ++index;
  1989. }
  1990. if (index === length) {
  1991. this._json = this._json.slice(startIndex);
  1992. return true;
  1993. }
  1994. this._array[this._arrayIndex++] = nextNumber;
  1995. }
  1996. },
  1997.  
  1998. _parseStringsArray: function()
  1999. {
  2000. var closingBracketIndex = this._json.lastIndexOf("]");
  2001. if (closingBracketIndex === -1)
  2002. throw new Error("Incomplete JSON");
  2003. this._json = this._json.slice(0, closingBracketIndex + 1);
  2004. this._snapshot.strings = JSON.parse(this._json);
  2005. },
  2006.  
  2007.  
  2008. write: function(chunk)
  2009. {
  2010. this._json += chunk;
  2011. switch (this._state) {
  2012. case "find-snapshot-info": {
  2013. var snapshotToken = "\"snapshot\"";
  2014. var snapshotTokenIndex = this._json.indexOf(snapshotToken);
  2015. if (snapshotTokenIndex === -1)
  2016. throw new Error("Snapshot token not found");
  2017. this._json = this._json.slice(snapshotTokenIndex + snapshotToken.length + 1);
  2018. this._state = "parse-snapshot-info";
  2019. }
  2020. case "parse-snapshot-info": {
  2021. var closingBracketIndex = WebInspector.findBalancedCurlyBrackets(this._json);
  2022. if (closingBracketIndex === -1)
  2023. return;
  2024. this._snapshot.snapshot =   (JSON.parse(this._json.slice(0, closingBracketIndex)));
  2025. this._json = this._json.slice(closingBracketIndex);
  2026. this._state = "find-nodes";
  2027. }
  2028. case "find-nodes": {
  2029. var nodesToken = "\"nodes\"";
  2030. var nodesTokenIndex = this._json.indexOf(nodesToken);
  2031. if (nodesTokenIndex === -1)
  2032. return;
  2033. var bracketIndex = this._json.indexOf("[", nodesTokenIndex);
  2034. if (bracketIndex === -1)
  2035. return;
  2036. this._json = this._json.slice(bracketIndex + 1);
  2037. var node_fields_count = this._snapshot.snapshot.meta.node_fields.length;
  2038. var nodes_length = this._snapshot.snapshot.node_count * node_fields_count;
  2039. this._array = new Uint32Array(nodes_length);
  2040. this._arrayIndex = 0;
  2041. this._state = "parse-nodes";
  2042. }
  2043. case "parse-nodes": {
  2044. if (this._parseUintArray())
  2045. return;
  2046. this._snapshot.nodes = this._array;
  2047. this._state = "find-edges";
  2048. this._array = null;
  2049. }
  2050. case "find-edges": {
  2051. var edgesToken = "\"edges\"";
  2052. var edgesTokenIndex = this._json.indexOf(edgesToken);
  2053. if (edgesTokenIndex === -1)
  2054. return;
  2055. var bracketIndex = this._json.indexOf("[", edgesTokenIndex);
  2056. if (bracketIndex === -1)
  2057. return;
  2058. this._json = this._json.slice(bracketIndex + 1);
  2059. var edge_fields_count = this._snapshot.snapshot.meta.edge_fields.length;
  2060. var edges_length = this._snapshot.snapshot.edge_count * edge_fields_count;
  2061. this._array = new Uint32Array(edges_length);
  2062. this._arrayIndex = 0;
  2063. this._state = "parse-edges";
  2064. }
  2065. case "parse-edges": {
  2066. if (this._parseUintArray())
  2067. return;
  2068. this._snapshot.edges = this._array;
  2069. this._array = null;
  2070. this._state = "find-strings";
  2071. }
  2072. case "find-strings": {
  2073. var stringsToken = "\"strings\"";
  2074. var stringsTokenIndex = this._json.indexOf(stringsToken);
  2075. if (stringsTokenIndex === -1)
  2076. return;
  2077. var bracketIndex = this._json.indexOf("[", stringsTokenIndex);
  2078. if (bracketIndex === -1)
  2079. return;
  2080. this._json = this._json.slice(bracketIndex);
  2081. this._state = "accumulate-strings";
  2082. break;
  2083. }
  2084. case "accumulate-strings":
  2085. break;
  2086. }
  2087. }
  2088. };
  2089. ;
  2090.  
  2091.  
  2092.  
  2093. WebInspector.HeapSnapshotWorkerDispatcher = function(globalObject, postMessage)
  2094. {
  2095. this._objects = [];
  2096. this._global = globalObject;
  2097. this._postMessage = postMessage;
  2098. }
  2099.  
  2100. WebInspector.HeapSnapshotWorkerDispatcher.prototype = {
  2101. _findFunction: function(name)
  2102. {
  2103. var path = name.split(".");
  2104. var result = this._global;
  2105. for (var i = 0; i < path.length; ++i)
  2106. result = result[path[i]];
  2107. return result;
  2108. },
  2109.  
  2110. dispatchMessage: function(event)
  2111. {
  2112. var data = event.data;
  2113. var response = {callId: data.callId};
  2114. try {
  2115. switch (data.disposition) {
  2116. case "create": {
  2117. var constructorFunction = this._findFunction(data.methodName);
  2118. this._objects[data.objectId] = new constructorFunction();
  2119. break;
  2120. }
  2121. case "dispose": {
  2122. delete this._objects[data.objectId];
  2123. break;
  2124. }
  2125. case "getter": {
  2126. var object = this._objects[data.objectId];
  2127. var result = object[data.methodName];
  2128. response.result = result;
  2129. break;
  2130. }
  2131. case "factory": {
  2132. var object = this._objects[data.objectId];
  2133. var result = object[data.methodName].apply(object, data.methodArguments);
  2134. if (result)
  2135. this._objects[data.newObjectId] = result;
  2136. response.result = !!result;
  2137. break;
  2138. }
  2139. case "method": {
  2140. var object = this._objects[data.objectId];
  2141. response.result = object[data.methodName].apply(object, data.methodArguments);
  2142. break;
  2143. }
  2144. }
  2145. } catch (e) {
  2146. response.error = e.toString();
  2147. response.errorCallStack = e.stack;
  2148. if (data.methodName)
  2149. response.errorMethodName = data.methodName;
  2150. }
  2151. this._postMessage(response);
  2152. }
  2153. };
  2154. ;
  2155.  
  2156.  
  2157.  
  2158. WebInspector.OutputStreamDelegate = function()
  2159. {
  2160. }
  2161.  
  2162. WebInspector.OutputStreamDelegate.prototype = {
  2163. onTransferStarted: function() { },
  2164.  
  2165. onTransferFinished: function() { },
  2166.  
  2167.  
  2168. onChunkTransferred: function(reader) { },
  2169.  
  2170.  
  2171. onError: function(reader, event) { },
  2172. }
  2173.  
  2174.  
  2175. WebInspector.OutputStream = function()
  2176. {
  2177. }
  2178.  
  2179. WebInspector.OutputStream.prototype = {
  2180.  
  2181. write: function(data, callback) { },
  2182.  
  2183. close: function() { }
  2184. }
  2185.  
  2186.  
  2187. WebInspector.ChunkedReader = function()
  2188. {
  2189. }
  2190.  
  2191. WebInspector.ChunkedReader.prototype = {
  2192.  
  2193. fileSize: function() { },
  2194.  
  2195.  
  2196. loadedSize: function() { },
  2197.  
  2198.  
  2199. fileName: function() { },
  2200.  
  2201. cancel: function() { }
  2202. }
  2203.  
  2204.  
  2205. WebInspector.ChunkedFileReader = function(file, chunkSize, delegate)
  2206. {
  2207. this._file = file;
  2208. this._fileSize = file.size;
  2209. this._loadedSize = 0;
  2210. this._chunkSize = chunkSize;
  2211. this._delegate = delegate;
  2212. this._isCanceled = false;
  2213. }
  2214.  
  2215. WebInspector.ChunkedFileReader.prototype = {
  2216.  
  2217. start: function(output)
  2218. {
  2219. this._output = output;
  2220.  
  2221. this._reader = new FileReader();
  2222. this._reader.onload = this._onChunkLoaded.bind(this);
  2223. this._reader.onerror = this._delegate.onError.bind(this._delegate, this);
  2224. this._delegate.onTransferStarted();
  2225. this._loadChunk();
  2226. },
  2227.  
  2228. cancel: function()
  2229. {
  2230. this._isCanceled = true;
  2231. },
  2232.  
  2233.  
  2234. loadedSize: function()
  2235. {
  2236. return this._loadedSize;
  2237. },
  2238.  
  2239.  
  2240. fileSize: function()
  2241. {
  2242. return this._fileSize;
  2243. },
  2244.  
  2245.  
  2246. fileName: function()
  2247. {
  2248. return this._file.name;
  2249. },
  2250.  
  2251.  
  2252. _onChunkLoaded: function(event)
  2253. {
  2254. if (this._isCanceled)
  2255. return;
  2256.  
  2257. if (event.target.readyState !== FileReader.DONE)
  2258. return;
  2259.  
  2260. var data = event.target.result;
  2261. this._loadedSize += data.length;
  2262.  
  2263. this._output.write(data);
  2264. if (this._isCanceled)
  2265. return;
  2266. this._delegate.onChunkTransferred(this);
  2267.  
  2268. if (this._loadedSize === this._fileSize) {
  2269. this._file = null;
  2270. this._reader = null;
  2271. this._output.close();
  2272. this._delegate.onTransferFinished();
  2273. return;
  2274. }
  2275.  
  2276. this._loadChunk();
  2277. },
  2278.  
  2279. _loadChunk: function()
  2280. {
  2281. var chunkStart = this._loadedSize;
  2282. var chunkEnd = Math.min(this._fileSize, chunkStart + this._chunkSize)
  2283. var nextPart = this._file.slice(chunkStart, chunkEnd);
  2284. this._reader.readAsText(nextPart);
  2285. }
  2286. }
  2287.  
  2288.  
  2289. WebInspector.ChunkedXHRReader = function(url, delegate)
  2290. {
  2291. this._url = url;
  2292. this._delegate = delegate;
  2293. this._fileSize = 0;
  2294. this._loadedSize = 0;
  2295. this._isCanceled = false;
  2296. }
  2297.  
  2298. WebInspector.ChunkedXHRReader.prototype = {
  2299.  
  2300. start: function(output)
  2301. {
  2302. this._output = output;
  2303.  
  2304. this._xhr = new XMLHttpRequest();
  2305. this._xhr.open("GET", this._url, true);
  2306. this._xhr.onload = this._onLoad.bind(this);
  2307. this._xhr.onprogress = this._onProgress.bind(this);
  2308. this._xhr.onerror = this._delegate.onError.bind(this._delegate, this);
  2309. this._xhr.send(null);
  2310.  
  2311. this._delegate.onTransferStarted();
  2312. },
  2313.  
  2314. cancel: function()
  2315. {
  2316. this._isCanceled = true;
  2317. this._xhr.abort();
  2318. },
  2319.  
  2320.  
  2321. loadedSize: function()
  2322. {
  2323. return this._loadedSize;
  2324. },
  2325.  
  2326.  
  2327. fileSize: function()
  2328. {
  2329. return this._fileSize;
  2330. },
  2331.  
  2332.  
  2333. fileName: function()
  2334. {
  2335. return this._url;
  2336. },
  2337.  
  2338.  
  2339. _onProgress: function(event)
  2340. {
  2341. if (this._isCanceled)
  2342. return;
  2343.  
  2344. if (event.lengthComputable)
  2345. this._fileSize = event.total;
  2346.  
  2347. var data = this._xhr.responseText.substring(this._loadedSize);
  2348. if (!data.length)
  2349. return;
  2350.  
  2351. this._loadedSize += data.length;
  2352. this._output.write(data);
  2353. if (this._isCanceled)
  2354. return;
  2355. this._delegate.onChunkTransferred(this);
  2356. },
  2357.  
  2358.  
  2359. _onLoad: function(event)
  2360. {
  2361. this._onProgress(event);
  2362.  
  2363. if (this._isCanceled)
  2364. return;
  2365.  
  2366. this._output.close();
  2367. this._delegate.onTransferFinished();
  2368. }
  2369. }
  2370.  
  2371.  
  2372. WebInspector.createFileSelectorElement = function(callback) {
  2373. var fileSelectorElement = document.createElement("input");
  2374. fileSelectorElement.type = "file";
  2375. fileSelectorElement.style.zIndex = -1;
  2376. fileSelectorElement.style.position = "absolute";
  2377. fileSelectorElement.onchange = function(event) {
  2378. callback(fileSelectorElement.files[0]);
  2379. };
  2380. return fileSelectorElement;
  2381. }
  2382.  
  2383.  
  2384. WebInspector.findBalancedCurlyBrackets = function(source, startIndex, lastIndex) {
  2385. lastIndex = lastIndex || source.length;
  2386. startIndex = startIndex || 0;
  2387. var counter = 0;
  2388. var inString = false;
  2389.  
  2390. for (var index = startIndex; index < lastIndex; ++index) {
  2391. var character = source[index];
  2392. if (inString) {
  2393. if (character === "\\")
  2394. ++index;
  2395. else if (character === "\"")
  2396. inString = false;
  2397. } else {
  2398. if (character === "\"")
  2399. inString = true;
  2400. else if (character === "{")
  2401. ++counter;
  2402. else if (character === "}") {
  2403. if (--counter === 0)
  2404. return index + 1;
  2405. }
  2406. }
  2407. }
  2408. return -1;
  2409. }
  2410.  
  2411.  
  2412. WebInspector.FileOutputStream = function()
  2413. {
  2414. }
  2415.  
  2416. WebInspector.FileOutputStream.prototype = {
  2417.  
  2418. open: function(fileName, callback)
  2419. {
  2420. this._closed = false;
  2421. this._writeCallbacks = [];
  2422. this._fileName = fileName;
  2423. function callbackWrapper()
  2424. {
  2425. WebInspector.fileManager.removeEventListener(WebInspector.FileManager.EventTypes.SavedURL, callbackWrapper, this);
  2426. WebInspector.fileManager.addEventListener(WebInspector.FileManager.EventTypes.AppendedToURL, this._onAppendDone, this);
  2427. callback(this);
  2428. }
  2429. WebInspector.fileManager.addEventListener(WebInspector.FileManager.EventTypes.SavedURL, callbackWrapper, this);
  2430. WebInspector.fileManager.save(this._fileName, "", true);
  2431. },
  2432.  
  2433.  
  2434. write: function(data, callback)
  2435. {
  2436. this._writeCallbacks.push(callback);
  2437. WebInspector.fileManager.append(this._fileName, data);
  2438. },
  2439.  
  2440. close: function()
  2441. {
  2442. this._closed = true;
  2443. if (this._writeCallbacks.length)
  2444. return;
  2445. WebInspector.fileManager.removeEventListener(WebInspector.FileManager.EventTypes.AppendedToURL, this._onAppendDone, this);
  2446. WebInspector.fileManager.close(this._fileName);
  2447. },
  2448.  
  2449.  
  2450. _onAppendDone: function(event)
  2451. {
  2452. if (event.data !== this._fileName)
  2453. return;
  2454. if (!this._writeCallbacks.length) {
  2455. if (this._closed) {
  2456. WebInspector.fileManager.removeEventListener(WebInspector.FileManager.EventTypes.AppendedToURL, this._onAppendDone, this);
  2457. WebInspector.fileManager.close(this._fileName);
  2458. }
  2459. return;
  2460. }
  2461. var callback = this._writeCallbacks.shift();
  2462. if (callback)
  2463. callback(this);
  2464. }
  2465. }
  2466. ;
  2467.  
  2468.  
  2469. Object.isEmpty = function(obj)
  2470. {
  2471. for (var i in obj)
  2472. return false;
  2473. return true;
  2474. }
  2475.  
  2476. Object.values = function(obj)
  2477. {
  2478. var keys = Object.keys(obj);
  2479. var result = [];
  2480.  
  2481. for (var i = 0; i < keys.length; ++i)
  2482. result.push(obj[keys[i]]);
  2483. return result;
  2484. }
  2485.  
  2486. String.prototype.hasSubstring = function(string, caseInsensitive)
  2487. {
  2488. if (!caseInsensitive)
  2489. return this.indexOf(string) !== -1;
  2490. return this.match(new RegExp(string.escapeForRegExp(), "i"));
  2491. }
  2492.  
  2493. String.prototype.findAll = function(string)
  2494. {
  2495. var matches = [];
  2496. var i = this.indexOf(string);
  2497. while (i !== -1) {
  2498. matches.push(i);
  2499. i = this.indexOf(string, i + string.length);
  2500. }
  2501. return matches;
  2502. }
  2503.  
  2504. String.prototype.lineEndings = function()
  2505. {
  2506. if (!this._lineEndings) {
  2507. this._lineEndings = this.findAll("\n");
  2508. this._lineEndings.push(this.length);
  2509. }
  2510. return this._lineEndings;
  2511. }
  2512.  
  2513. String.prototype.escapeCharacters = function(chars)
  2514. {
  2515. var foundChar = false;
  2516. for (var i = 0; i < chars.length; ++i) {
  2517. if (this.indexOf(chars.charAt(i)) !== -1) {
  2518. foundChar = true;
  2519. break;
  2520. }
  2521. }
  2522.  
  2523. if (!foundChar)
  2524. return this;
  2525.  
  2526. var result = "";
  2527. for (var i = 0; i < this.length; ++i) {
  2528. if (chars.indexOf(this.charAt(i)) !== -1)
  2529. result += "\\";
  2530. result += this.charAt(i);
  2531. }
  2532.  
  2533. return result;
  2534. }
  2535.  
  2536. String.prototype.escapeForRegExp = function()
  2537. {
  2538. return this.escapeCharacters("^[]{}()\\.$*+?|");
  2539. }
  2540.  
  2541. String.prototype.escapeHTML = function()
  2542. {
  2543. return this.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """); 
  2544. }
  2545.  
  2546. String.prototype.collapseWhitespace = function()
  2547. {
  2548. return this.replace(/[\s\xA0]+/g, " ");
  2549. }
  2550.  
  2551. String.prototype.trimMiddle = function(maxLength)
  2552. {
  2553. if (this.length <= maxLength)
  2554. return this;
  2555. var leftHalf = maxLength >> 1;
  2556. var rightHalf = maxLength - leftHalf - 1;
  2557. return this.substr(0, leftHalf) + "\u2026" + this.substr(this.length - rightHalf, rightHalf);
  2558. }
  2559.  
  2560. String.prototype.trimEnd = function(maxLength)
  2561. {
  2562. if (this.length <= maxLength)
  2563. return this;
  2564. return this.substr(0, maxLength - 1) + "\u2026";
  2565. }
  2566.  
  2567. String.prototype.trimURL = function(baseURLDomain)
  2568. {
  2569. var result = this.replace(/^(https|http|file):\/\//i, "");
  2570. if (baseURLDomain)
  2571. result = result.replace(new RegExp("^" + baseURLDomain.escapeForRegExp(), "i"), "");
  2572. return result;
  2573. }
  2574.  
  2575.  
  2576. function sanitizeHref(href)
  2577. {
  2578. return href && href.trim().toLowerCase().startsWith("javascript:") ? "" : href;
  2579. }
  2580.  
  2581. String.prototype.removeURLFragment = function()
  2582. {
  2583. var fragmentIndex = this.indexOf("#");
  2584. if (fragmentIndex == -1)
  2585. fragmentIndex = this.length;
  2586. return this.substring(0, fragmentIndex);
  2587. }
  2588.  
  2589. String.prototype.startsWith = function(substring)
  2590. {
  2591. return !this.lastIndexOf(substring, 0);
  2592. }
  2593.  
  2594. String.prototype.endsWith = function(substring)
  2595. {
  2596. return this.indexOf(substring, this.length - substring.length) !== -1;
  2597. }
  2598.  
  2599. Number.constrain = function(num, min, max)
  2600. {
  2601. if (num < min)
  2602. num = min;
  2603. else if (num > max)
  2604. num = max;
  2605. return num;
  2606. }
  2607.  
  2608. Date.prototype.toISO8601Compact = function()
  2609. {
  2610. function leadZero(x)
  2611. {
  2612. return x > 9 ? '' + x : '0' + x
  2613. }
  2614. return this.getFullYear() +
  2615. leadZero(this.getMonth() + 1) +
  2616. leadZero(this.getDate()) + 'T' +
  2617. leadZero(this.getHours()) +
  2618. leadZero(this.getMinutes()) +
  2619. leadZero(this.getSeconds());
  2620. }
  2621.  
  2622. Object.defineProperty(Array.prototype, "remove",
  2623. {
  2624.  
  2625. value: function(value, onlyFirst)
  2626. {
  2627. if (onlyFirst) {
  2628. var index = this.indexOf(value);
  2629. if (index !== -1)
  2630. this.splice(index, 1);
  2631. return;
  2632. }
  2633.  
  2634. var length = this.length;
  2635. for (var i = 0; i < length; ++i) {
  2636. if (this[i] === value)
  2637. this.splice(i, 1);
  2638. }
  2639. }
  2640. });
  2641.  
  2642. Object.defineProperty(Array.prototype, "keySet",
  2643. {
  2644.  
  2645. value: function()
  2646. {
  2647. var keys = {};
  2648. for (var i = 0; i < this.length; ++i)
  2649. keys[this[i]] = true;
  2650. return keys;
  2651. }
  2652. });
  2653.  
  2654. Object.defineProperty(Array.prototype, "upperBound",
  2655. {
  2656.  
  2657. value: function(value)
  2658. {
  2659. var first = 0;
  2660. var count = this.length;
  2661. while (count > 0) {
  2662. var step = count >> 1;
  2663. var middle = first + step;
  2664. if (value >= this[middle]) {
  2665. first = middle + 1;
  2666. count -= step + 1;
  2667. } else
  2668. count = step;
  2669. }
  2670. return first;
  2671. }
  2672. });
  2673.  
  2674. Object.defineProperty(Array.prototype, "rotate",
  2675. {
  2676.  
  2677. value: function(index)
  2678. {
  2679. var result = [];
  2680. for (var i = index; i < index + this.length; ++i)
  2681. result.push(this[i % this.length]);
  2682. return result;
  2683. }
  2684. });
  2685.  
  2686. Object.defineProperty(Uint32Array.prototype, "sort", {
  2687. value: Array.prototype.sort
  2688. });
  2689.  
  2690. (function() {
  2691. var partition = {
  2692.  
  2693. value: function(comparator, left, right, pivotIndex)
  2694. {
  2695. function swap(array, i1, i2)
  2696. {
  2697. var temp = array[i1];
  2698. array[i1] = array[i2];
  2699. array[i2] = temp;
  2700. }
  2701.  
  2702. var pivotValue = this[pivotIndex];
  2703. swap(this, right, pivotIndex);
  2704. var storeIndex = left;
  2705. for (var i = left; i < right; ++i) {
  2706. if (comparator(this[i], pivotValue) < 0) {
  2707. swap(this, storeIndex, i);
  2708. ++storeIndex;
  2709. }
  2710. }
  2711. swap(this, right, storeIndex);
  2712. return storeIndex;
  2713. }
  2714. };
  2715. Object.defineProperty(Array.prototype, "partition", partition);
  2716. Object.defineProperty(Uint32Array.prototype, "partition", partition);
  2717.  
  2718. var sortRange = {
  2719.  
  2720. value: function(comparator, leftBound, rightBound, k)
  2721. {
  2722. function quickSortFirstK(array, comparator, left, right, k)
  2723. {
  2724. if (right <= left)
  2725. return;
  2726. var pivotIndex = Math.floor(Math.random() * (right - left)) + left;
  2727. var pivotNewIndex = array.partition(comparator, left, right, pivotIndex);
  2728. quickSortFirstK(array, comparator, left, pivotNewIndex - 1, k);
  2729. if (pivotNewIndex < left + k - 1)
  2730. quickSortFirstK(array, comparator, pivotNewIndex + 1, right, k);
  2731. }
  2732.  
  2733. if (leftBound === 0 && rightBound === (this.length - 1) && k === this.length)
  2734. this.sort(comparator);
  2735. else
  2736. quickSortFirstK(this, comparator, leftBound, rightBound, k);
  2737. return this;
  2738. }
  2739. }
  2740. Object.defineProperty(Array.prototype, "sortRange", sortRange);
  2741. Object.defineProperty(Uint32Array.prototype, "sortRange", sortRange);
  2742. })();
  2743.  
  2744. Object.defineProperty(Array.prototype, "qselect",
  2745. {
  2746.  
  2747. value: function(k, comparator)
  2748. {
  2749. if (k < 0 || k >= this.length)
  2750. return;
  2751. if (!comparator)
  2752. comparator = function(a, b) { return a - b; }
  2753.  
  2754. var low = 0;
  2755. var high = this.length - 1;
  2756. for (;;) {
  2757. var pivotPosition = this.partition(comparator, low, high, Math.floor((high + low) / 2));
  2758. if (pivotPosition === k)
  2759. return this[k];
  2760. else if (pivotPosition > k)
  2761. high = pivotPosition - 1;
  2762. else
  2763. low = pivotPosition + 1;
  2764. }
  2765. }
  2766. });
  2767.  
  2768.  
  2769. function binarySearch(object, array, comparator)
  2770. {
  2771. var first = 0;
  2772. var last = array.length - 1;
  2773.  
  2774. while (first <= last) {
  2775. var mid = (first + last) >> 1;
  2776. var c = comparator(object, array[mid]);
  2777. if (c > 0)
  2778. first = mid + 1;
  2779. else if (c < 0)
  2780. last = mid - 1;
  2781. else
  2782. return mid;
  2783. }
  2784.  
  2785.  
  2786. return -(first + 1);
  2787. }
  2788.  
  2789. Object.defineProperty(Array.prototype, "binaryIndexOf",
  2790. {
  2791.  
  2792. value: function(value, comparator)
  2793. {
  2794. var result = binarySearch(value, this, comparator);
  2795. return result >= 0 ? result : -1;
  2796. }
  2797. });
  2798.  
  2799. Object.defineProperty(Array.prototype, "select",
  2800. {
  2801.  
  2802. value: function(field)
  2803. {
  2804. var result = new Array(this.length);
  2805. for (var i = 0; i < this.length; ++i)
  2806. result[i] = this[i][field];
  2807. return result;
  2808. }
  2809. });
  2810.  
  2811.  
  2812. function insertionIndexForObjectInListSortedByFunction(anObject, aList, aFunction)
  2813. {
  2814. var index = binarySearch(anObject, aList, aFunction);
  2815. if (index < 0)
  2816.  
  2817. return -index - 1;
  2818. else {
  2819.  
  2820. while (index > 0 && aFunction(anObject, aList[index - 1]) === 0)
  2821. index--;
  2822. return index;
  2823. }
  2824. }
  2825.  
  2826.  
  2827. String.sprintf = function(format, var_arg)
  2828. {
  2829. return String.vsprintf(format, Array.prototype.slice.call(arguments, 1));
  2830. }
  2831.  
  2832. String.tokenizeFormatString = function(format, formatters)
  2833. {
  2834. var tokens = [];
  2835. var substitutionIndex = 0;
  2836.  
  2837. function addStringToken(str)
  2838. {
  2839. tokens.push({ type: "string", value: str });
  2840. }
  2841.  
  2842. function addSpecifierToken(specifier, precision, substitutionIndex)
  2843. {
  2844. tokens.push({ type: "specifier", specifier: specifier, precision: precision, substitutionIndex: substitutionIndex });
  2845. }
  2846.  
  2847. function isDigit(c)
  2848. {
  2849. return !!/[0-9]/.exec(c);
  2850. }
  2851.  
  2852. var index = 0;
  2853. for (var precentIndex = format.indexOf("%", index); precentIndex !== -1; precentIndex = format.indexOf("%", index)) {
  2854. addStringToken(format.substring(index, precentIndex));
  2855. index = precentIndex + 1;
  2856.  
  2857. if (isDigit(format[index])) {
  2858.  
  2859. var number = parseInt(format.substring(index), 10);
  2860. while (isDigit(format[index]))
  2861. ++index;
  2862.  
  2863.  
  2864.  
  2865. if (number > 0 && format[index] === "$") {
  2866. substitutionIndex = (number - 1);
  2867. ++index;
  2868. }
  2869. }
  2870.  
  2871. var precision = -1;
  2872. if (format[index] === ".") {
  2873.  
  2874.  
  2875. ++index;
  2876. precision = parseInt(format.substring(index), 10);
  2877. if (isNaN(precision))
  2878. precision = 0;
  2879.  
  2880. while (isDigit(format[index]))
  2881. ++index;
  2882. }
  2883.  
  2884. if (!(format[index] in formatters)) {
  2885. addStringToken(format.substring(precentIndex, index + 1));
  2886. ++index;
  2887. continue;
  2888. }
  2889.  
  2890. addSpecifierToken(format[index], precision, substitutionIndex);
  2891.  
  2892. ++substitutionIndex;
  2893. ++index;
  2894. }
  2895.  
  2896. addStringToken(format.substring(index));
  2897.  
  2898. return tokens;
  2899. }
  2900.  
  2901. String.standardFormatters = {
  2902. d: function(substitution)
  2903. {
  2904. return !isNaN(substitution) ? substitution : 0;
  2905. },
  2906.  
  2907. f: function(substitution, token)
  2908. {
  2909. if (substitution && token.precision > -1)
  2910. substitution = substitution.toFixed(token.precision);
  2911. return !isNaN(substitution) ? substitution : (token.precision > -1 ? Number(0).toFixed(token.precision) : 0);
  2912. },
  2913.  
  2914. s: function(substitution)
  2915. {
  2916. return substitution;
  2917. }
  2918. }
  2919.  
  2920. String.vsprintf = function(format, substitutions)
  2921. {
  2922. return String.format(format, substitutions, String.standardFormatters, "", function(a, b) { return a + b; }).formattedResult;
  2923. }
  2924.  
  2925. String.format = function(format, substitutions, formatters, initialValue, append)
  2926. {
  2927. if (!format || !substitutions || !substitutions.length)
  2928. return { formattedResult: append(initialValue, format), unusedSubstitutions: substitutions };
  2929.  
  2930. function prettyFunctionName()
  2931. {
  2932. return "String.format(\"" + format + "\", \"" + substitutions.join("\", \"") + "\")";
  2933. }
  2934.  
  2935. function warn(msg)
  2936. {
  2937. console.warn(prettyFunctionName() + ": " + msg);
  2938. }
  2939.  
  2940. function error(msg)
  2941. {
  2942. console.error(prettyFunctionName() + ": " + msg);
  2943. }
  2944.  
  2945. var result = initialValue;
  2946. var tokens = String.tokenizeFormatString(format, formatters);
  2947. var usedSubstitutionIndexes = {};
  2948.  
  2949. for (var i = 0; i < tokens.length; ++i) {
  2950. var token = tokens[i];
  2951.  
  2952. if (token.type === "string") {
  2953. result = append(result, token.value);
  2954. continue;
  2955. }
  2956.  
  2957. if (token.type !== "specifier") {
  2958. error("Unknown token type \"" + token.type + "\" found.");
  2959. continue;
  2960. }
  2961.  
  2962. if (token.substitutionIndex >= substitutions.length) {
  2963.  
  2964.  
  2965. error("not enough substitution arguments. Had " + substitutions.length + " but needed " + (token.substitutionIndex + 1) + ", so substitution was skipped.");
  2966. result = append(result, "%" + (token.precision > -1 ? token.precision : "") + token.specifier);
  2967. continue;
  2968. }
  2969.  
  2970. usedSubstitutionIndexes[token.substitutionIndex] = true;
  2971.  
  2972. if (!(token.specifier in formatters)) {
  2973.  
  2974. warn("unsupported format character \u201C" + token.specifier + "\u201D. Treating as a string.");
  2975. result = append(result, substitutions[token.substitutionIndex]);
  2976. continue;
  2977. }
  2978.  
  2979. result = append(result, formatters[token.specifier](substitutions[token.substitutionIndex], token));
  2980. }
  2981.  
  2982. var unusedSubstitutions = [];
  2983. for (var i = 0; i < substitutions.length; ++i) {
  2984. if (i in usedSubstitutionIndexes)
  2985. continue;
  2986. unusedSubstitutions.push(substitutions[i]);
  2987. }
  2988.  
  2989. return { formattedResult: result, unusedSubstitutions: unusedSubstitutions };
  2990. }
  2991.  
  2992.  
  2993. function createSearchRegex(query, caseSensitive, isRegex)
  2994. {
  2995. var regexFlags = caseSensitive ? "g" : "gi";
  2996. var regexObject;
  2997.  
  2998. if (isRegex) {
  2999. try {
  3000. regexObject = new RegExp(query, regexFlags);
  3001. } catch (e) {
  3002.  
  3003. }
  3004. }
  3005.  
  3006. if (!regexObject)
  3007. regexObject = createPlainTextSearchRegex(query, regexFlags);
  3008.  
  3009. return regexObject;
  3010. }
  3011.  
  3012.  
  3013. function createPlainTextSearchRegex(query, flags)
  3014. {
  3015.  
  3016. var regexSpecialCharacters = "[](){}+-*.,?\\^$|";
  3017. var regex = "";
  3018. for (var i = 0; i < query.length; ++i) {
  3019. var c = query.charAt(i);
  3020. if (regexSpecialCharacters.indexOf(c) != -1)
  3021. regex += "\\";
  3022. regex += c;
  3023. }
  3024. return new RegExp(regex, flags || "");
  3025. }
  3026.  
  3027.  
  3028. function countRegexMatches(regex, content)
  3029. {
  3030. var text = content;
  3031. var result = 0;
  3032. var match;
  3033. while (text && (match = regex.exec(text))) {
  3034. if (match[0].length > 0)
  3035. ++result;
  3036. text = text.substring(match.index + 1);
  3037. }
  3038. return result;
  3039. }
  3040.  
  3041.  
  3042. function numberToStringWithSpacesPadding(value, symbolsCount)
  3043. {
  3044. var numberString = value.toString();
  3045. var paddingLength = Math.max(0, symbolsCount - numberString.length);
  3046. var paddingString = Array(paddingLength + 1).join("\u00a0");
  3047. return paddingString + numberString;
  3048. }
  3049.  
  3050.  
  3051. var Map = function()
  3052. {
  3053. this._map = {};
  3054. this._size = 0;
  3055. }
  3056.  
  3057. Map._lastObjectIdentifier = 0;
  3058.  
  3059. Map.prototype = {
  3060.  
  3061. put: function(key, value)
  3062. {
  3063. var objectIdentifier = key.__identifier;
  3064. if (!objectIdentifier) {
  3065. objectIdentifier = ++Map._lastObjectIdentifier;
  3066. key.__identifier = objectIdentifier;
  3067. }
  3068. if (!this._map[objectIdentifier])
  3069. ++this._size;
  3070. this._map[objectIdentifier] = [key, value];
  3071. },
  3072.  
  3073.  
  3074. remove: function(key)
  3075. {
  3076. var result = this._map[key.__identifier];
  3077. if (!result)
  3078. return undefined;
  3079. --this._size;
  3080. delete this._map[key.__identifier];
  3081. return result[1];
  3082. },
  3083.  
  3084.  
  3085. keys: function()
  3086. {
  3087. return this._list(0);
  3088. },
  3089.  
  3090. values: function()
  3091. {
  3092. return this._list(1);
  3093. },
  3094.  
  3095.  
  3096. _list: function(index)
  3097. {
  3098. var result = new Array(this._size);
  3099. var i = 0;
  3100. for (var objectIdentifier in this._map)
  3101. result[i++] = this._map[objectIdentifier][index];
  3102. return result;
  3103. },
  3104.  
  3105.  
  3106. get: function(key)
  3107. {
  3108. var entry = this._map[key.__identifier];
  3109. return entry ? entry[1] : undefined;
  3110. },
  3111.  
  3112. size: function()
  3113. {
  3114. return this._size;
  3115. },
  3116.  
  3117. clear: function()
  3118. {
  3119. this._map = {};
  3120. this._size = 0;
  3121. }
  3122. }
  3123.  
  3124. function loadXHR(url, async, callback) 
  3125. {
  3126. function onReadyStateChanged() 
  3127. {
  3128. if (xhr.readyState !== XMLHttpRequest.DONE)
  3129. return;
  3130.  
  3131. if (xhr.status === 200) {
  3132. callback(xhr.responseText);
  3133. return;
  3134. }
  3135.  
  3136. callback(null); 
  3137. }
  3138.  
  3139. var xhr = new XMLHttpRequest();
  3140. xhr.open("GET", url, async);
  3141. if (async)
  3142. xhr.onreadystatechange = onReadyStateChanged;        
  3143. xhr.send(null);
  3144.  
  3145. if (!async) {
  3146. if (xhr.status === 200) 
  3147. return xhr.responseText;
  3148. return null;
  3149. }
  3150. return null;
  3151. }
  3152.  
  3153.  
  3154. function StringPool()
  3155. {
  3156. this.reset();
  3157. }
  3158.  
  3159. StringPool.prototype = {
  3160.  
  3161. intern: function(string)
  3162. {
  3163.  
  3164. if (string === "__proto__")
  3165. return "__proto__";
  3166. var result = this._strings[string];
  3167. if (result === undefined) {
  3168. this._strings[string] = string;
  3169. result = string;
  3170. }
  3171. return result;
  3172. },
  3173.  
  3174. reset: function()
  3175. {
  3176. this._strings = Object.create(null);
  3177. },
  3178.  
  3179.  
  3180. internObjectStrings: function(obj, depthLimit)
  3181. {
  3182. if (typeof depthLimit !== "number")
  3183. depthLimit = 100;
  3184. else if (--depthLimit < 0)
  3185. throw "recursion depth limit reached in StringPool.deepIntern(), perhaps attempting to traverse cyclical references?";
  3186.  
  3187. for (var field in obj) {
  3188. switch (typeof obj[field]) {
  3189. case "string":
  3190. obj[field] = this.intern(obj[field]);
  3191. break;
  3192. case "object":
  3193. this.internObjectStrings(obj[field], depthLimit);
  3194. break;
  3195. }
  3196. }
  3197. }
  3198. }
  3199.  
  3200. var _importedScripts = {};
  3201.  
  3202.  
  3203. function importScript(scriptName)
  3204. {
  3205. if (_importedScripts[scriptName])
  3206. return;
  3207. _importedScripts[scriptName] = true;
  3208. var xhr = new XMLHttpRequest();
  3209. xhr.open("GET", scriptName, false);
  3210. xhr.send(null);
  3211. window.eval(xhr.responseText + "\n//@ sourceURL=" + scriptName);
  3212. }
  3213. ;
  3214.  
  3215. function postMessageWrapper(message)
  3216. {
  3217. postMessage(message);
  3218. }
  3219.  
  3220.  
  3221. WebInspector.WorkerConsole = function()
  3222. {
  3223. }
  3224.  
  3225. WebInspector.WorkerConsole.prototype = {
  3226.  
  3227. log: function(var_args)
  3228. {
  3229. this._postMessage("log", Array.prototype.slice.call(arguments));
  3230. },
  3231.  
  3232.  
  3233. error: function(var_args)
  3234. {
  3235. this._postMessage("error", Array.prototype.slice.call(arguments));
  3236. },
  3237.  
  3238.  
  3239. info: function(var_args)
  3240. {
  3241. this._postMessage("info", Array.prototype.slice.call(arguments));
  3242. },
  3243.  
  3244. trace: function()
  3245. {
  3246. this.log(new Error().stack);
  3247. },
  3248.  
  3249.  
  3250.  
  3251. _postMessage: function(method, args)
  3252. {
  3253. var rawMessage = {
  3254. object: "console",
  3255. method: method,
  3256. arguments: args
  3257. };
  3258. postMessageWrapper(rawMessage);
  3259. }
  3260. };
  3261.  
  3262. var dispatcher = new WebInspector.HeapSnapshotWorkerDispatcher(this, postMessageWrapper);
  3263. addEventListener("message", dispatcher.dispatchMessage.bind(dispatcher), false);
  3264. console = new WebInspector.WorkerConsole();
  3265.